5#include "flutter/shell/common/engine.h"
9#include "flutter/runtime/dart_vm_lifecycle.h"
10#include "flutter/shell/common/thread_host.h"
11#include "flutter/testing/fixture_test.h"
12#include "flutter/testing/testing.h"
14#include "gmock/gmock.h"
16#include "rapidjson/document.h"
17#include "rapidjson/stringbuffer.h"
18#include "rapidjson/writer.h"
26class FontManifestAssetResolver :
public AssetResolver {
28 FontManifestAssetResolver() {}
30 bool IsValid()
const override {
return true; }
32 bool IsValidAfterAssetManagerChange()
const override {
return true; }
35 return AssetResolver::AssetResolverType::kApkAssetProvider;
39 std::unique_ptr<fml::Mapping> GetAsMapping(
40 const std::string& asset_name)
const override {
42 if (asset_name ==
"FontManifest.json") {
43 return std::make_unique<fml::DataMapping>(
"[{},{},{}]");
48 std::vector<std::unique_ptr<fml::Mapping>> GetAsMappings(
49 const std::string& asset_pattern,
50 const std::optional<std::string>& subdir)
const override {
54 bool operator==(
const AssetResolver& other)
const override {
55 auto mapping = GetAsMapping(
"FontManifest.json");
56 return memcmp(other.GetAsMapping(
"FontManifest.json")->GetMapping(),
57 mapping->GetMapping(), mapping->GetSize()) == 0;
61class MockDelegate :
public Engine::Delegate {
64 OnEngineUpdateSemantics,
68 OnEngineHandlePlatformMessage,
69 (std::unique_ptr<PlatformMessage>),
71 MOCK_METHOD(
void, OnPreEngineRestart, (), (
override));
72 MOCK_METHOD(
void, OnRootIsolateCreated, (), (
override));
74 UpdateIsolateDescription,
75 (
const std::string, int64_t),
77 MOCK_METHOD(
void, SetNeedsReportTimings, (
bool), (
override));
78 MOCK_METHOD(std::unique_ptr<std::vector<std::string>>,
79 ComputePlatformResolvedLocale,
80 (
const std::vector<std::string>&),
82 MOCK_METHOD(
void, RequestDartDeferredLibrary, (intptr_t), (
override));
84 MOCK_METHOD(
const std::shared_ptr<PlatformMessageHandler>&,
85 GetPlatformMessageHandler,
88 MOCK_METHOD(
void, OnEngineChannelUpdate, (std::string,
bool), (
override));
97 MOCK_METHOD(
void, Complete, (std::unique_ptr<fml::Mapping>
data), (
override));
98 MOCK_METHOD(
void, CompleteEmpty, (), (
override));
101class MockRuntimeDelegate :
public RuntimeDelegate {
103 MOCK_METHOD(std::string, DefaultRouteName, (), (
override));
105 MOCK_METHOD(
void, OnAllViewsRendered, (), (
override));
108 (int64_t, std::unique_ptr<flutter::LayerTree>,
float),
115 HandlePlatformMessage,
116 (std::unique_ptr<PlatformMessage>),
118 MOCK_METHOD(FontCollection&, GetFontCollection, (), (
override));
119 MOCK_METHOD(std::shared_ptr<AssetManager>, GetAssetManager, (), (
override));
120 MOCK_METHOD(
void, OnRootIsolateCreated, (), (
override));
122 UpdateIsolateDescription,
123 (
const std::string, int64_t),
125 MOCK_METHOD(
void, SetNeedsReportTimings, (
bool), (
override));
126 MOCK_METHOD(std::unique_ptr<std::vector<std::string>>,
127 ComputePlatformResolvedLocale,
128 (
const std::vector<std::string>&),
130 MOCK_METHOD(
void, RequestDartDeferredLibrary, (intptr_t), (
override));
131 MOCK_METHOD(std::weak_ptr<PlatformMessageHandler>,
132 GetPlatformMessageHandler,
135 MOCK_METHOD(
void, SendChannelUpdate, (std::string,
bool), (
override));
138 (
double font_size,
int configuration_id),
142class MockRuntimeController :
public RuntimeController {
144 MockRuntimeController(RuntimeDelegate& client,
145 const TaskRunners& p_task_runners)
146 : RuntimeController(client, p_task_runners) {}
147 MOCK_METHOD(
bool, IsRootIsolateRunning, (), (
override));
150 (std::unique_ptr<PlatformMessage>),
153 LoadDartDeferredLibraryError,
154 (intptr_t,
const std::string,
bool),
156 MOCK_METHOD(DartVM*, GetDartVM, (), (
const,
override));
160class MockFontCollection :
public FontCollection {
164 (
const std::shared_ptr<AssetManager>& asset_manager),
168std::unique_ptr<PlatformMessage> MakePlatformMessage(
169 const std::string& channel,
170 const std::map<std::string, std::string>&
values,
172 rapidjson::Document document;
173 auto& allocator = document.GetAllocator();
174 document.SetObject();
176 for (
const auto& pair :
values) {
177 rapidjson::Value
key(pair.first.c_str(), strlen(pair.first.c_str()),
179 rapidjson::Value
value(pair.second.c_str(), strlen(pair.second.c_str()),
181 document.AddMember(
key,
value, allocator);
184 rapidjson::StringBuffer
buffer;
185 rapidjson::Writer<rapidjson::StringBuffer> writer(
buffer);
186 document.Accept(writer);
187 const uint8_t*
data =
reinterpret_cast<const uint8_t*
>(
buffer.GetString());
189 std::unique_ptr<PlatformMessage>
message = std::make_unique<PlatformMessage>(
194class EngineTest :
public testing::FixtureTest {
198 ThreadHost::
Type::kPlatform | ThreadHost::
Type::kIo |
218 void SetUp()
override {
239 PostUITaskSync([
this] {
240 auto engine = std::make_unique<Engine>(
248 std::make_shared<FontCollection>(),
250 std::make_shared<fml::SyncSwitch>());
255TEST_F(EngineTest, DispatchPlatformMessageUnknown) {
256 PostUITaskSync([
this] {
257 MockRuntimeDelegate client;
258 auto mock_runtime_controller =
259 std::make_unique<MockRuntimeController>(client,
task_runners_);
260 EXPECT_CALL(*mock_runtime_controller, IsRootIsolateRunning())
261 .WillRepeatedly(::testing::Return(
false));
262 auto engine = std::make_unique<Engine>(
270 std::make_shared<FontCollection>(),
271 std::move(mock_runtime_controller),
272 std::make_shared<fml::SyncSwitch>());
275 fml::MakeRefCounted<MockResponse>();
276 std::unique_ptr<PlatformMessage>
message =
277 std::make_unique<PlatformMessage>(
"foo", response);
282TEST_F(EngineTest, DispatchPlatformMessageInitialRoute) {
283 PostUITaskSync([
this] {
284 MockRuntimeDelegate client;
285 auto mock_runtime_controller =
286 std::make_unique<MockRuntimeController>(client,
task_runners_);
287 EXPECT_CALL(*mock_runtime_controller, IsRootIsolateRunning())
288 .WillRepeatedly(::testing::Return(
false));
289 auto engine = std::make_unique<Engine>(
297 std::make_shared<FontCollection>(),
298 std::move(mock_runtime_controller),
299 std::make_shared<fml::SyncSwitch>());
302 fml::MakeRefCounted<MockResponse>();
303 std::map<std::string, std::string>
values{
304 {
"method",
"setInitialRoute"},
305 {
"args",
"test_initial_route"},
307 std::unique_ptr<PlatformMessage>
message =
308 MakePlatformMessage(
"flutter/navigation",
values, response);
310 EXPECT_EQ(
engine->InitialRoute(),
"test_initial_route");
314TEST_F(EngineTest, DispatchPlatformMessageInitialRouteIgnored) {
315 PostUITaskSync([
this] {
316 MockRuntimeDelegate client;
317 auto mock_runtime_controller =
318 std::make_unique<MockRuntimeController>(client,
task_runners_);
319 EXPECT_CALL(*mock_runtime_controller, IsRootIsolateRunning())
320 .WillRepeatedly(::testing::Return(
true));
322 .WillRepeatedly(::testing::Return(
true));
323 auto engine = std::make_unique<Engine>(
331 std::make_shared<FontCollection>(),
332 std::move(mock_runtime_controller),
333 std::make_shared<fml::SyncSwitch>());
336 fml::MakeRefCounted<MockResponse>();
337 std::map<std::string, std::string>
values{
338 {
"method",
"setInitialRoute"},
339 {
"args",
"test_initial_route"},
341 std::unique_ptr<PlatformMessage>
message =
342 MakePlatformMessage(
"flutter/navigation",
values, response);
344 EXPECT_EQ(
engine->InitialRoute(),
"");
348TEST_F(EngineTest, SpawnSharesFontLibrary) {
349 PostUITaskSync([
this] {
350 MockRuntimeDelegate client;
351 auto mock_runtime_controller =
352 std::make_unique<MockRuntimeController>(client,
task_runners_);
354 EXPECT_CALL(*mock_runtime_controller, GetDartVM())
355 .WillRepeatedly(::testing::Return(vm_ref.get()));
356 auto engine = std::make_unique<Engine>(
364 std::make_shared<FontCollection>(),
365 std::move(mock_runtime_controller),
366 std::make_shared<fml::SyncSwitch>());
372 EXPECT_EQ(&
engine->GetFontCollection(), &
spawn->GetFontCollection());
376TEST_F(EngineTest, SpawnWithCustomInitialRoute) {
377 PostUITaskSync([
this] {
378 MockRuntimeDelegate client;
379 auto mock_runtime_controller =
380 std::make_unique<MockRuntimeController>(client,
task_runners_);
382 EXPECT_CALL(*mock_runtime_controller, GetDartVM())
383 .WillRepeatedly(::testing::Return(vm_ref.get()));
384 auto engine = std::make_unique<Engine>(
392 std::make_shared<FontCollection>(),
393 std::move(mock_runtime_controller),
394 std::make_shared<fml::SyncSwitch>());
400 ASSERT_EQ(
"/foo",
spawn->InitialRoute());
404TEST_F(EngineTest, SpawnWithCustomSettings) {
405 PostUITaskSync([
this] {
406 MockRuntimeDelegate client;
407 auto mock_runtime_controller =
408 std::make_unique<MockRuntimeController>(client,
task_runners_);
410 EXPECT_CALL(*mock_runtime_controller, GetDartVM())
411 .WillRepeatedly(::testing::Return(vm_ref.get()));
412 auto engine = std::make_unique<Engine>(
420 std::make_shared<FontCollection>(),
421 std::move(mock_runtime_controller),
422 std::make_shared<fml::SyncSwitch>());
426 std::make_shared<fml::DataMapping>(
"foo");
431 auto new_persistent_isolate_data =
433 ->GetPersistentIsolateData();
435 new_persistent_isolate_data->GetMapping());
437 new_persistent_isolate_data->GetSize());
441TEST_F(EngineTest, PassesLoadDartDeferredLibraryErrorToRuntime) {
442 PostUITaskSync([
this] {
443 intptr_t error_id = 123;
444 const std::string error_message =
"error message";
445 MockRuntimeDelegate client;
446 auto mock_runtime_controller =
447 std::make_unique<MockRuntimeController>(client,
task_runners_);
448 EXPECT_CALL(*mock_runtime_controller, IsRootIsolateRunning())
449 .WillRepeatedly(::testing::Return(
true));
450 EXPECT_CALL(*mock_runtime_controller,
451 LoadDartDeferredLibraryError(error_id, error_message,
true))
453 auto engine = std::make_unique<Engine>(
461 std::make_shared<FontCollection>(),
462 std::move(mock_runtime_controller),
463 std::make_shared<fml::SyncSwitch>());
465 engine->LoadDartDeferredLibraryError(error_id, error_message,
true);
469TEST_F(EngineTest, SpawnedEngineInheritsAssetManager) {
470 PostUITaskSync([
this] {
471 MockRuntimeDelegate client;
472 auto mock_runtime_controller =
473 std::make_unique<MockRuntimeController>(client,
task_runners_);
475 EXPECT_CALL(*mock_runtime_controller, GetDartVM())
476 .WillRepeatedly(::testing::Return(vm_ref.get()));
481 auto engine = std::make_unique<Engine>(
489 std::make_shared<FontCollection>(),
490 std::move(mock_runtime_controller),
491 std::make_shared<fml::SyncSwitch>());
493 EXPECT_EQ(
engine->GetAssetManager(),
nullptr);
495 auto asset_manager = std::make_shared<AssetManager>();
496 asset_manager->PushBack(std::make_unique<FontManifestAssetResolver>());
497 engine->UpdateAssetManager(asset_manager);
498 EXPECT_EQ(
engine->GetAssetManager(), asset_manager);
504 EXPECT_EQ(
engine->GetAssetManager(),
spawn->GetAssetManager());
508TEST_F(EngineTest, UpdateAssetManagerWithEqualManagers) {
509 PostUITaskSync([
this] {
510 MockRuntimeDelegate client;
511 auto mock_runtime_controller =
512 std::make_unique<MockRuntimeController>(client,
task_runners_);
514 EXPECT_CALL(*mock_runtime_controller, GetDartVM())
515 .WillRepeatedly(::testing::Return(vm_ref.get()));
517 auto mock_font_collection = std::make_shared<MockFontCollection>();
518 EXPECT_CALL(*mock_font_collection, RegisterFonts(::testing::_))
519 .WillOnce(::testing::Return());
520 auto engine = std::make_unique<Engine>(
528 mock_font_collection,
529 std::move(mock_runtime_controller),
530 std::make_shared<fml::SyncSwitch>());
532 EXPECT_EQ(
engine->GetAssetManager(),
nullptr);
534 auto asset_manager = std::make_shared<AssetManager>();
535 asset_manager->PushBack(std::make_unique<FontManifestAssetResolver>());
537 auto asset_manager_2 = std::make_shared<AssetManager>();
538 asset_manager_2->PushBack(std::make_unique<FontManifestAssetResolver>());
540 EXPECT_NE(asset_manager, asset_manager_2);
543 engine->UpdateAssetManager(asset_manager);
544 EXPECT_EQ(
engine->GetAssetManager(), asset_manager);
546 engine->UpdateAssetManager(asset_manager_2);
548 EXPECT_EQ(
engine->GetAssetManager(), asset_manager);
static sk_sp< Effect > Create()
AssetResolverType
Identifies the type of AssetResolver an instance is.
static DartVMRef Create(const Settings &settings, fml::RefPtr< const DartSnapshot > vm_snapshot=nullptr, fml::RefPtr< const DartSnapshot > isolate_snapshot=nullptr)
static MallocMapping Copy(const T *begin, const T *end)
std::shared_ptr< fml::ConcurrentTaskRunner > image_decoder_task_runner_
std::unique_ptr< RuntimeController > runtime_controller_
TaskRunners task_runners_
fml::TaskRunnerAffineWeakPtr< SnapshotDelegate > snapshot_delegate_
std::unique_ptr< Animator > animator_
PointerDataDispatcherMaker dispatcher_maker_
fml::WeakPtr< IOManager > io_manager_
size_t mapping_call_count
@ kRaster
Suitable for thread which raster data.
Dart_NativeFunction function
static Dart_TypedData_Type GetType(intptr_t class_id)
std::unordered_map< int32_t, SemanticsNode > SemanticsNodeUpdates
std::unordered_map< int32_t, CustomAccessibilityAction > CustomAccessibilityActionUpdates
std::function< std::unique_ptr< PointerDataDispatcher >(PointerDataDispatcher::Delegate &)> PointerDataDispatcherMaker
Signature for constructing PointerDataDispatcher.
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
static void DispatchPlatformMessage(JNIEnv *env, jobject jcaller, jlong shell_holder, jstring channel, jobject message, jint position, jint responseId)
bool operator==(const ViewportMetrics &a, const ViewportMetrics &b)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
static void ScheduleFrame(JNIEnv *env, jobject jcaller, jlong shell_holder)
TEST_F(EngineAnimatorTest, AnimatorAcceptsMultipleRenders)
std::shared_ptr< const fml::Mapping > persistent_isolate_data
#define EXPECT_TRUE(handle)