6 #include "gtest/gtest.h"
8 #include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h"
18 TEST(FlEngineTest, NotifyDisplayUpdate) {
22 g_autoptr(GError)
error =
nullptr;
24 EXPECT_EQ(
error,
nullptr);
29 ([&called](
auto engine, FlutterEngineDisplaysUpdateType update_type,
30 const FlutterEngineDisplay* displays,
size_t displays_length) {
32 EXPECT_EQ(update_type, kFlutterEngineDisplaysUpdateTypeStartup);
33 EXPECT_EQ(displays_length, 2u);
35 EXPECT_EQ(displays[0].display_id, 1u);
36 EXPECT_EQ(displays[0].refresh_rate, 60);
37 EXPECT_EQ(displays[0].
width, 1024u);
38 EXPECT_EQ(displays[0].
height, 768u);
39 EXPECT_EQ(displays[0].device_pixel_ratio, 1.0);
41 EXPECT_EQ(displays[1].display_id, 2u);
42 EXPECT_EQ(displays[1].refresh_rate, 120);
43 EXPECT_EQ(displays[1].
width, 3840u);
44 EXPECT_EQ(displays[1].
height, 2160u);
45 EXPECT_EQ(displays[1].device_pixel_ratio, 2.0);
50 FlutterEngineDisplay displays[2] = {
52 .struct_size =
sizeof(FlutterEngineDisplay),
54 .single_display =
false,
58 .device_pixel_ratio = 1.0,
61 .struct_size =
sizeof(FlutterEngineDisplay),
63 .single_display =
false,
64 .refresh_rate = 120.0,
67 .device_pixel_ratio = 2.0,
75 TEST(FlEngineTest, WindowMetrics) {
79 g_autoptr(GError)
error =
nullptr;
81 EXPECT_EQ(
error,
nullptr);
85 SendWindowMetricsEvent,
86 ([&called](
auto engine,
const FlutterWindowMetricsEvent* event) {
88 EXPECT_EQ(event->display_id, 99u);
89 EXPECT_EQ(event->view_id, 1);
90 EXPECT_EQ(event->width,
static_cast<size_t>(3840));
91 EXPECT_EQ(event->height,
static_cast<size_t>(2160));
92 EXPECT_EQ(event->pixel_ratio, 2.0);
103 TEST(FlEngineTest, MousePointer) {
110 ([&called](
auto engine,
const FlutterPointerEvent* events,
111 size_t events_count) {
113 EXPECT_EQ(events_count,
static_cast<size_t>(1));
114 EXPECT_EQ(events[0].view_id, 1);
115 EXPECT_EQ(events[0].phase, kDown);
116 EXPECT_EQ(events[0].timestamp,
static_cast<size_t>(1234567890));
117 EXPECT_EQ(events[0].x, 800);
118 EXPECT_EQ(events[0].y, 600);
119 EXPECT_EQ(events[0].device,
static_cast<int32_t
>(0));
120 EXPECT_EQ(events[0].signal_kind, kFlutterPointerSignalKindScroll);
121 EXPECT_EQ(events[0].scroll_delta_x, 1.2);
122 EXPECT_EQ(events[0].scroll_delta_y, -3.4);
123 EXPECT_EQ(events[0].device_kind, kFlutterPointerDeviceKindMouse);
124 EXPECT_EQ(events[0].buttons, kFlutterPointerButtonMouseSecondary);
129 g_autoptr(GError)
error =
nullptr;
131 EXPECT_EQ(
error,
nullptr);
133 kFlutterPointerDeviceKindMouse, 1.2, -3.4,
134 kFlutterPointerButtonMouseSecondary);
140 TEST(FlEngineTest, PointerPanZoom) {
147 ([&called](
auto engine,
const FlutterPointerEvent* events,
148 size_t events_count) {
150 EXPECT_EQ(events_count,
static_cast<size_t>(1));
151 EXPECT_EQ(events[0].view_id, 1);
152 EXPECT_EQ(events[0].phase, kPanZoomUpdate);
153 EXPECT_EQ(events[0].timestamp,
static_cast<size_t>(1234567890));
154 EXPECT_EQ(events[0].x, 800);
155 EXPECT_EQ(events[0].y, 600);
156 EXPECT_EQ(events[0].device,
static_cast<int32_t
>(1));
157 EXPECT_EQ(events[0].signal_kind, kFlutterPointerSignalKindNone);
158 EXPECT_EQ(events[0].pan_x, 1.5);
159 EXPECT_EQ(events[0].pan_y, 2.5);
160 EXPECT_EQ(events[0].scale, 3.5);
161 EXPECT_EQ(events[0].rotation, 4.5);
162 EXPECT_EQ(events[0].device_kind, kFlutterPointerDeviceKindTrackpad);
163 EXPECT_EQ(events[0].buttons, 0);
168 g_autoptr(GError)
error =
nullptr;
170 EXPECT_EQ(
error,
nullptr);
172 kPanZoomUpdate, 1.5, 2.5, 3.5, 4.5);
178 TEST(FlEngineTest, DispatchSemanticsAction) {
185 DispatchSemanticsAction,
186 ([&called](
auto engine, uint64_t
id, FlutterSemanticsAction action,
187 const uint8_t* data,
size_t data_length) {
188 EXPECT_EQ(
id,
static_cast<uint64_t
>(42));
189 EXPECT_EQ(action, kFlutterSemanticsActionTap);
190 EXPECT_EQ(data_length,
static_cast<size_t>(4));
191 EXPECT_EQ(data[0],
't');
192 EXPECT_EQ(data[1],
'e');
193 EXPECT_EQ(data[2],
's');
194 EXPECT_EQ(data[3],
't');
200 g_autoptr(GError)
error =
nullptr;
202 EXPECT_EQ(
error,
nullptr);
203 g_autoptr(GBytes) data = g_bytes_new_static(
"test", 4);
211 TEST(FlEngineTest, PlatformMessage) {
216 FlutterEngineSendPlatformMessageFnPtr old_handler =
220 ([&called, old_handler](
auto engine,
221 const FlutterPlatformMessage* message) {
222 if (strcmp(message->channel,
"test") != 0) {
223 return old_handler(engine, message);
228 EXPECT_EQ(message->message_size,
static_cast<size_t>(4));
229 EXPECT_EQ(message->message[0],
't');
230 EXPECT_EQ(message->message[1],
'e');
231 EXPECT_EQ(message->message[2],
's');
232 EXPECT_EQ(message->message[3],
't');
237 g_autoptr(GError)
error =
nullptr;
239 EXPECT_EQ(
error,
nullptr);
240 g_autoptr(GBytes) message = g_bytes_new_static(
"test", 4);
248 TEST(FlEngineTest, PlatformMessageResponse) {
255 SendPlatformMessageResponse,
256 ([&called](
auto engine,
257 const FlutterPlatformMessageResponseHandle* handle,
258 const uint8_t* data,
size_t data_length) {
263 reinterpret_cast<const FlutterPlatformMessageResponseHandle*
>(
265 EXPECT_EQ(data_length,
static_cast<size_t>(4));
266 EXPECT_EQ(data[0],
't');
267 EXPECT_EQ(data[1],
'e');
268 EXPECT_EQ(data[2],
's');
269 EXPECT_EQ(data[3],
't');
274 g_autoptr(GError)
error =
nullptr;
276 EXPECT_EQ(
error,
nullptr);
277 g_autoptr(GBytes) response = g_bytes_new_static(
"test", 4);
279 engine,
reinterpret_cast<const FlutterPlatformMessageResponseHandle*
>(42),
281 EXPECT_EQ(
error,
nullptr);
287 TEST(FlEngineTest, SettingsHandler) {
294 ([&called](
auto engine,
const FlutterPlatformMessage* message) {
297 EXPECT_STREQ(message->channel,
"flutter/settings");
300 g_autoptr(GBytes) data =
301 g_bytes_new(message->message, message->message_size);
302 g_autoptr(GError)
error =
nullptr;
304 FL_MESSAGE_CODEC(codec), data, &
error);
305 EXPECT_NE(settings,
nullptr);
306 EXPECT_EQ(
error,
nullptr);
310 EXPECT_NE(text_scale_factor,
nullptr);
313 FlValue* always_use_24hr_format =
315 EXPECT_NE(always_use_24hr_format,
nullptr);
321 EXPECT_NE(platform_brightness,
nullptr);
327 g_autoptr(GError)
error =
nullptr;
329 EXPECT_EQ(
error,
nullptr);
335 int* count =
reinterpret_cast<int*
>(
user_data);
340 TEST(FlEngineTest, OnPreEngineRestart) {
344 OnPreEngineRestartCallback callback;
345 void* callback_user_data;
349 Initialize, ([&callback, &callback_user_data, &called](
350 size_t version,
const FlutterRendererConfig* config,
352 FLUTTER_API_SYMBOL(FlutterEngine) * engine_out) {
354 callback =
args->on_pre_engine_restart_callback;
360 MOCK_ENGINE_PROC(RunInitialized, ([](
auto engine) {
return kSuccess; }));
362 g_autoptr(GError)
error =
nullptr;
364 EXPECT_EQ(
error,
nullptr);
367 EXPECT_NE(callback,
nullptr);
370 callback(callback_user_data);
378 g_signal_connect(engine,
"on-pre-engine-restart",
381 callback(callback_user_data);
385 TEST(FlEngineTest, DartEntrypointArgs) {
386 GPtrArray* args_array = g_ptr_array_new();
387 g_ptr_array_add(args_array,
const_cast<char*
>(
"arg_one"));
388 g_ptr_array_add(args_array,
const_cast<char*
>(
"arg_two"));
389 g_ptr_array_add(args_array,
const_cast<char*
>(
"arg_three"));
390 g_ptr_array_add(args_array,
nullptr);
391 gchar**
args =
reinterpret_cast<gchar**
>(g_ptr_array_free(args_array,
false));
399 Initialize, ([&called, &set_args =
args](
400 size_t version,
const FlutterRendererConfig* config,
402 FLUTTER_API_SYMBOL(FlutterEngine) * engine_out) {
404 EXPECT_NE(set_args,
args->dart_entrypoint_argv);
405 EXPECT_EQ(
args->dart_entrypoint_argc, 3);
410 MOCK_ENGINE_PROC(RunInitialized, ([](
auto engine) {
return kSuccess; }));
412 g_autoptr(GError)
error =
nullptr;
414 EXPECT_EQ(
error,
nullptr);
425 ([&engine_id](
size_t version,
const FlutterRendererConfig* config,
427 FLUTTER_API_SYMBOL(FlutterEngine) * engine_out) {
428 engine_id =
args->engine_id;
432 MOCK_ENGINE_PROC(RunInitialized, ([](
auto engine) {
return kSuccess; }));
434 g_autoptr(GError)
error =
nullptr;
436 EXPECT_EQ(
error,
nullptr);
437 EXPECT_TRUE(engine_id != 0);
443 g_autofree gchar* initial_language = g_strdup(g_getenv(
"LANGUAGE"));
444 g_setenv(
"LANGUAGE",
"de:en_US",
TRUE);
451 UpdateLocales, ([&called](
auto engine,
const FlutterLocale** locales,
452 size_t locales_count) {
455 EXPECT_EQ(locales_count,
static_cast<size_t>(4));
457 EXPECT_STREQ(locales[0]->language_code,
"de");
458 EXPECT_STREQ(locales[0]->country_code,
nullptr);
459 EXPECT_STREQ(locales[0]->script_code,
nullptr);
460 EXPECT_STREQ(locales[0]->variant_code,
nullptr);
462 EXPECT_STREQ(locales[1]->language_code,
"en");
463 EXPECT_STREQ(locales[1]->country_code,
"US");
464 EXPECT_STREQ(locales[1]->script_code,
nullptr);
465 EXPECT_STREQ(locales[1]->variant_code,
nullptr);
467 EXPECT_STREQ(locales[2]->language_code,
"en");
468 EXPECT_STREQ(locales[2]->country_code,
nullptr);
469 EXPECT_STREQ(locales[2]->script_code,
nullptr);
470 EXPECT_STREQ(locales[2]->variant_code,
nullptr);
472 EXPECT_STREQ(locales[3]->language_code,
"C");
473 EXPECT_STREQ(locales[3]->country_code,
nullptr);
474 EXPECT_STREQ(locales[3]->script_code,
nullptr);
475 EXPECT_STREQ(locales[3]->variant_code,
nullptr);
480 g_autoptr(GError)
error =
nullptr;
482 EXPECT_EQ(
error,
nullptr);
486 if (initial_language) {
487 g_setenv(
"LANGUAGE", initial_language,
TRUE);
489 g_unsetenv(
"LANGUAGE");
494 g_autofree gchar* initial_language = g_strdup(g_getenv(
"LANGUAGE"));
495 g_setenv(
"LANGUAGE",
"C",
TRUE);
502 UpdateLocales, ([&called](
auto engine,
const FlutterLocale** locales,
503 size_t locales_count) {
506 EXPECT_EQ(locales_count,
static_cast<size_t>(1));
508 EXPECT_STREQ(locales[0]->language_code,
"C");
509 EXPECT_STREQ(locales[0]->country_code,
nullptr);
510 EXPECT_STREQ(locales[0]->script_code,
nullptr);
511 EXPECT_STREQ(locales[0]->variant_code,
nullptr);
516 g_autoptr(GError)
error =
nullptr;
518 EXPECT_EQ(
error,
nullptr);
522 if (initial_language) {
523 g_setenv(
"LANGUAGE", initial_language,
TRUE);
525 g_unsetenv(
"LANGUAGE");
529 TEST(FlEngineTest, DuplicateLocale) {
530 g_autofree gchar* initial_language = g_strdup(g_getenv(
"LANGUAGE"));
531 g_setenv(
"LANGUAGE",
"en:en",
TRUE);
538 UpdateLocales, ([&called](
auto engine,
const FlutterLocale** locales,
539 size_t locales_count) {
542 EXPECT_EQ(locales_count,
static_cast<size_t>(2));
544 EXPECT_STREQ(locales[0]->language_code,
"en");
545 EXPECT_STREQ(locales[0]->country_code,
nullptr);
546 EXPECT_STREQ(locales[0]->script_code,
nullptr);
547 EXPECT_STREQ(locales[0]->variant_code,
nullptr);
549 EXPECT_STREQ(locales[1]->language_code,
"C");
550 EXPECT_STREQ(locales[1]->country_code,
nullptr);
551 EXPECT_STREQ(locales[1]->script_code,
nullptr);
552 EXPECT_STREQ(locales[1]->variant_code,
nullptr);
557 g_autoptr(GError)
error =
nullptr;
559 EXPECT_EQ(
error,
nullptr);
563 if (initial_language) {
564 g_setenv(
"LANGUAGE", initial_language,
TRUE);
566 g_unsetenv(
"LANGUAGE");
570 TEST(FlEngineTest, EmptyLocales) {
571 g_autofree gchar* initial_language = g_strdup(g_getenv(
"LANGUAGE"));
572 g_setenv(
"LANGUAGE",
"de:: :en_US",
TRUE);
579 UpdateLocales, ([&called](
auto engine,
const FlutterLocale** locales,
580 size_t locales_count) {
583 EXPECT_EQ(locales_count,
static_cast<size_t>(4));
585 EXPECT_STREQ(locales[0]->language_code,
"de");
586 EXPECT_STREQ(locales[0]->country_code,
nullptr);
587 EXPECT_STREQ(locales[0]->script_code,
nullptr);
588 EXPECT_STREQ(locales[0]->variant_code,
nullptr);
590 EXPECT_STREQ(locales[1]->language_code,
"en");
591 EXPECT_STREQ(locales[1]->country_code,
"US");
592 EXPECT_STREQ(locales[1]->script_code,
nullptr);
593 EXPECT_STREQ(locales[1]->variant_code,
nullptr);
595 EXPECT_STREQ(locales[2]->language_code,
"en");
596 EXPECT_STREQ(locales[2]->country_code,
nullptr);
597 EXPECT_STREQ(locales[2]->script_code,
nullptr);
598 EXPECT_STREQ(locales[2]->variant_code,
nullptr);
600 EXPECT_STREQ(locales[3]->language_code,
"C");
601 EXPECT_STREQ(locales[3]->country_code,
nullptr);
602 EXPECT_STREQ(locales[3]->script_code,
nullptr);
603 EXPECT_STREQ(locales[3]->variant_code,
nullptr);
608 g_autoptr(GError)
error =
nullptr;
610 EXPECT_EQ(
error,
nullptr);
614 if (initial_language) {
615 g_setenv(
"LANGUAGE", initial_language,
TRUE);
617 g_unsetenv(
"LANGUAGE");
622 GAsyncResult* result,
624 g_autoptr(GError)
error =
nullptr;
627 EXPECT_EQ(
error,
nullptr);
629 g_main_loop_quit(
static_cast<GMainLoop*
>(
user_data));
633 g_autoptr(GMainLoop) loop = g_main_loop_new(
nullptr, 0);
640 AddView, ([&called](
auto engine,
const FlutterAddViewInfo* info) {
642 EXPECT_EQ(info->view_metrics->width, 123u);
643 EXPECT_EQ(info->view_metrics->height, 456u);
644 EXPECT_EQ(info->view_metrics->pixel_ratio, 2.0);
646 FlutterAddViewResult result;
647 result.struct_size =
sizeof(FlutterAddViewResult);
649 result.user_data = info->user_data;
650 info->add_view_callback(&result);
655 FlutterViewId view_id =
657 EXPECT_GT(view_id, 0);
661 g_main_loop_run(loop);
665 GAsyncResult* result,
667 g_autoptr(GError)
error =
nullptr;
670 EXPECT_NE(
error,
nullptr);
672 g_main_loop_quit(
static_cast<GMainLoop*
>(
user_data));
675 TEST(FlEngineTest, AddViewError) {
676 g_autoptr(GMainLoop) loop = g_main_loop_new(
nullptr, 0);
682 AddView, ([](
auto engine,
const FlutterAddViewInfo* info) {
683 FlutterAddViewResult result;
684 result.struct_size =
sizeof(FlutterAddViewResult);
685 result.added =
false;
686 result.user_data = info->user_data;
687 info->add_view_callback(&result);
694 EXPECT_GT(view_id, 0);
697 g_main_loop_run(loop);
701 GAsyncResult* result,
703 g_autoptr(GError)
error =
nullptr;
706 EXPECT_NE(
error,
nullptr);
708 g_main_loop_quit(
static_cast<GMainLoop*
>(
user_data));
711 TEST(FlEngineTest, AddViewEngineError) {
712 g_autoptr(GMainLoop) loop = g_main_loop_new(
nullptr, 0);
718 AddView, ([](
auto engine,
const FlutterAddViewInfo* info) {
719 return kInvalidArguments;
724 EXPECT_GT(view_id, 0);
727 g_main_loop_run(loop);
731 GAsyncResult* result,
733 g_autoptr(GError)
error =
nullptr;
736 EXPECT_EQ(
error,
nullptr);
738 g_main_loop_quit(
static_cast<GMainLoop*
>(
user_data));
741 TEST(FlEngineTest, RemoveView) {
742 g_autoptr(GMainLoop) loop = g_main_loop_new(
nullptr, 0);
749 RemoveView, ([&called](
auto engine,
const FlutterRemoveViewInfo* info) {
751 EXPECT_EQ(info->view_id, 123);
753 FlutterRemoveViewResult result;
754 result.struct_size =
sizeof(FlutterRemoveViewResult);
755 result.removed =
true;
756 result.user_data = info->user_data;
757 info->remove_view_callback(&result);
766 g_main_loop_run(loop);
770 GAsyncResult* result,
772 g_autoptr(GError)
error =
nullptr;
775 EXPECT_NE(
error,
nullptr);
777 g_main_loop_quit(
static_cast<GMainLoop*
>(
user_data));
780 TEST(FlEngineTest, RemoveViewError) {
781 g_autoptr(GMainLoop) loop = g_main_loop_new(
nullptr, 0);
787 RemoveView, ([](
auto engine,
const FlutterRemoveViewInfo* info) {
788 FlutterRemoveViewResult result;
789 result.struct_size =
sizeof(FlutterRemoveViewResult);
790 result.removed =
false;
791 result.user_data = info->user_data;
792 info->remove_view_callback(&result);
800 g_main_loop_run(loop);
804 GAsyncResult* result,
806 g_autoptr(GError)
error =
nullptr;
809 EXPECT_NE(
error,
nullptr);
811 g_main_loop_quit(
static_cast<GMainLoop*
>(
user_data));
814 TEST(FlEngineTest, RemoveViewEngineError) {
815 g_autoptr(GMainLoop) loop = g_main_loop_new(
nullptr, 0);
821 RemoveView, ([](
auto engine,
const FlutterRemoveViewInfo* info) {
822 return kInvalidArguments;
829 g_main_loop_run(loop);
832 TEST(FlEngineTest, SendKeyEvent) {
833 g_autoptr(GMainLoop) loop = g_main_loop_new(
nullptr, 0);
838 g_autoptr(GError)
error =
nullptr;
840 EXPECT_EQ(
error,
nullptr);
845 ([&called](
auto engine,
const FlutterKeyEvent* event,
846 FlutterKeyEventCallback callback,
void*
user_data) {
848 EXPECT_EQ(event->timestamp, 1234);
849 EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
850 EXPECT_EQ(event->physical,
static_cast<uint64_t
>(42));
851 EXPECT_EQ(event->logical,
static_cast<uint64_t
>(123));
852 EXPECT_TRUE(event->synthesized);
853 EXPECT_EQ(event->device_type, kFlutterKeyEventDeviceTypeKeyboard);
858 FlutterKeyEvent
event = {.struct_size =
sizeof(FlutterKeyEvent),
860 .
type = kFlutterKeyEventTypeUp,
863 .character =
nullptr,
865 .device_type = kFlutterKeyEventDeviceTypeKeyboard};
867 engine, &event,
nullptr,
868 [](GObject*
object, GAsyncResult* result, gpointer
user_data) {
870 g_autoptr(GError)
error =
nullptr;
873 EXPECT_EQ(
error,
nullptr);
874 EXPECT_TRUE(handled);
875 g_main_loop_quit(
static_cast<GMainLoop*
>(
user_data));
879 g_main_loop_run(loop);
883 TEST(FlEngineTest, SendKeyEventNotHandled) {
884 g_autoptr(GMainLoop) loop = g_main_loop_new(
nullptr, 0);
889 g_autoptr(GError)
error =
nullptr;
891 EXPECT_EQ(
error,
nullptr);
896 ([&called](
auto engine,
const FlutterKeyEvent* event,
897 FlutterKeyEventCallback callback,
void*
user_data) {
903 FlutterKeyEvent
event = {.struct_size =
sizeof(FlutterKeyEvent),
905 .
type = kFlutterKeyEventTypeUp,
908 .character =
nullptr,
910 .device_type = kFlutterKeyEventDeviceTypeKeyboard};
912 engine, &event,
nullptr,
913 [](GObject*
object, GAsyncResult* result, gpointer
user_data) {
915 g_autoptr(GError)
error =
nullptr;
918 EXPECT_EQ(
error,
nullptr);
919 EXPECT_FALSE(handled);
920 g_main_loop_quit(
static_cast<GMainLoop*
>(
user_data));
924 g_main_loop_run(loop);
928 TEST(FlEngineTest, SendKeyEventError) {
929 g_autoptr(GMainLoop) loop = g_main_loop_new(
nullptr, 0);
934 g_autoptr(GError)
error =
nullptr;
936 EXPECT_EQ(
error,
nullptr);
941 ([&called](
auto engine,
const FlutterKeyEvent* event,
942 FlutterKeyEventCallback callback,
void*
user_data) {
944 return kInvalidArguments;
947 FlutterKeyEvent
event = {.struct_size =
sizeof(FlutterKeyEvent),
949 .
type = kFlutterKeyEventTypeUp,
952 .character =
nullptr,
954 .device_type = kFlutterKeyEventDeviceTypeKeyboard};
956 engine, &event,
nullptr,
957 [](GObject*
object, GAsyncResult* result, gpointer
user_data) {
959 g_autoptr(GError)
error =
nullptr;
962 EXPECT_NE(
error,
nullptr);
963 EXPECT_STREQ(
error->message,
"Failed to send key event");
964 g_main_loop_quit(
static_cast<GMainLoop*
>(
user_data));
968 g_main_loop_run(loop);
972 TEST(FlEngineTest, ChildObjects) {