6#include "gtest/gtest.h"
19TEST(FlEngineTest, NotifyDisplayUpdate) {
25 EXPECT_EQ(
error,
nullptr);
34 EXPECT_EQ(displays_length, 2u);
36 EXPECT_EQ(
displays[0].display_id, 1u);
37 EXPECT_EQ(
displays[0].refresh_rate, 60);
40 EXPECT_EQ(
displays[0].device_pixel_ratio, 1.0);
42 EXPECT_EQ(
displays[1].display_id, 2u);
43 EXPECT_EQ(
displays[1].refresh_rate, 120);
46 EXPECT_EQ(
displays[1].device_pixel_ratio, 2.0);
55 .single_display =
false,
59 .device_pixel_ratio = 1.0,
64 .single_display =
false,
65 .refresh_rate = 120.0,
68 .device_pixel_ratio = 2.0,
76TEST(FlEngineTest, WindowMetrics) {
82 EXPECT_EQ(
error,
nullptr);
86 SendWindowMetricsEvent,
91 EXPECT_EQ(event->
width,
static_cast<size_t>(3840));
92 EXPECT_EQ(event->
height,
static_cast<size_t>(2160));
104TEST(FlEngineTest, MousePointer) {
112 size_t events_count) {
114 EXPECT_EQ(events_count,
static_cast<size_t>(1));
115 EXPECT_EQ(events[0].
view_id, 1);
116 EXPECT_EQ(events[0].phase,
kDown);
117 EXPECT_EQ(events[0].timestamp,
static_cast<size_t>(1234567890));
118 EXPECT_EQ(events[0].
x, 800);
119 EXPECT_EQ(events[0].
y, 600);
120 EXPECT_EQ(events[0].
device,
static_cast<int32_t
>(0));
122 EXPECT_EQ(events[0].scroll_delta_x, 1.2);
123 EXPECT_EQ(events[0].scroll_delta_y, -3.4);
132 EXPECT_EQ(
error,
nullptr);
141TEST(FlEngineTest, PointerPanZoom) {
149 size_t events_count) {
151 EXPECT_EQ(events_count,
static_cast<size_t>(1));
152 EXPECT_EQ(events[0].
view_id, 1);
154 EXPECT_EQ(events[0].timestamp,
static_cast<size_t>(1234567890));
155 EXPECT_EQ(events[0].
x, 800);
156 EXPECT_EQ(events[0].
y, 600);
157 EXPECT_EQ(events[0].
device,
static_cast<int32_t
>(1));
159 EXPECT_EQ(events[0].pan_x, 1.5);
160 EXPECT_EQ(events[0].pan_y, 2.5);
161 EXPECT_EQ(events[0].scale, 3.5);
162 EXPECT_EQ(events[0].rotation, 4.5);
164 EXPECT_EQ(events[0].buttons, 0);
171 EXPECT_EQ(
error,
nullptr);
179TEST(FlEngineTest, DispatchSemanticsAction) {
187 EXPECT_EQ(info->
view_id,
static_cast<int64_t
>(456));
188 EXPECT_EQ(info->
node_id,
static_cast<uint64_t
>(42));
190 EXPECT_EQ(info->
data_length,
static_cast<size_t>(4));
191 EXPECT_EQ(info->
data[0],
't');
192 EXPECT_EQ(info->
data[1],
'e');
193 EXPECT_EQ(info->
data[2],
's');
194 EXPECT_EQ(info->
data[3],
't');
202 EXPECT_EQ(
error,
nullptr);
220 ([&called, old_handler](
auto engine,
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');
239 EXPECT_EQ(
error,
nullptr);
255 SendPlatformMessageResponse,
258 const uint8_t*
data,
size_t data_length) {
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');
276 EXPECT_EQ(
error,
nullptr);
277 g_autoptr(GBytes) response = g_bytes_new_static(
"test", 4);
281 EXPECT_EQ(
error,
nullptr);
287TEST(FlEngineTest, SettingsHandler) {
297 EXPECT_STREQ(
message->channel,
"flutter/settings");
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);
329 EXPECT_EQ(
error,
nullptr);
335 int* count =
reinterpret_cast<int*
>(
user_data);
340TEST(FlEngineTest, OnPreEngineRestart) {
345 void* callback_user_data;
349 Initialize, ([&
callback, &callback_user_data, &called](
364 EXPECT_EQ(
error,
nullptr);
378 g_signal_connect(
engine,
"on-pre-engine-restart",
385TEST(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](
404 EXPECT_NE(set_args,
args->dart_entrypoint_argv);
405 EXPECT_EQ(
args->dart_entrypoint_argc, 3);
414 EXPECT_EQ(
error,
nullptr);
428 engine_id =
args->engine_id;
436 EXPECT_EQ(
error,
nullptr);
437 EXPECT_TRUE(engine_id != 0);
442TEST(FlEngineTest, UIIsolateDefaultThreadPolicy) {
447 bool same_task_runner =
false;
454 same_task_runner =
args->custom_task_runners->platform_task_runner ==
455 args->custom_task_runners->ui_task_runner;
463 EXPECT_EQ(
error,
nullptr);
464 EXPECT_TRUE(same_task_runner);
467TEST(FlEngineTest, UIIsolateOnPlatformTaskRunner) {
473 bool same_task_runner =
false;
480 same_task_runner =
args->custom_task_runners->platform_task_runner ==
481 args->custom_task_runners->ui_task_runner;
489 EXPECT_EQ(
error,
nullptr);
490 EXPECT_TRUE(same_task_runner);
493TEST(FlEngineTest, UIIsolateOnSeparateThread) {
499 bool separate_thread =
false;
506 separate_thread =
args->custom_task_runners->ui_task_runner ==
nullptr;
514 EXPECT_EQ(
error,
nullptr);
515 EXPECT_TRUE(separate_thread);
519 g_autofree gchar* initial_language = g_strdup(g_getenv(
"LANGUAGE"));
520 g_setenv(
"LANGUAGE",
"de:en_US",
TRUE);
528 size_t locales_count) {
531 EXPECT_EQ(locales_count,
static_cast<size_t>(4));
533 EXPECT_STREQ(locales[0]->language_code,
"de");
534 EXPECT_STREQ(locales[0]->country_code,
nullptr);
535 EXPECT_STREQ(locales[0]->script_code,
nullptr);
536 EXPECT_STREQ(locales[0]->variant_code,
nullptr);
538 EXPECT_STREQ(locales[1]->language_code,
"en");
539 EXPECT_STREQ(locales[1]->country_code,
"US");
540 EXPECT_STREQ(locales[1]->script_code,
nullptr);
541 EXPECT_STREQ(locales[1]->variant_code,
nullptr);
543 EXPECT_STREQ(locales[2]->language_code,
"en");
544 EXPECT_STREQ(locales[2]->country_code,
nullptr);
545 EXPECT_STREQ(locales[2]->script_code,
nullptr);
546 EXPECT_STREQ(locales[2]->variant_code,
nullptr);
548 EXPECT_STREQ(locales[3]->language_code,
"C");
549 EXPECT_STREQ(locales[3]->country_code,
nullptr);
550 EXPECT_STREQ(locales[3]->script_code,
nullptr);
551 EXPECT_STREQ(locales[3]->variant_code,
nullptr);
558 EXPECT_EQ(
error,
nullptr);
562 if (initial_language) {
563 g_setenv(
"LANGUAGE", initial_language,
TRUE);
565 g_unsetenv(
"LANGUAGE");
570 g_autofree gchar* initial_language = g_strdup(g_getenv(
"LANGUAGE"));
571 g_setenv(
"LANGUAGE",
"C",
TRUE);
579 size_t locales_count) {
582 EXPECT_EQ(locales_count,
static_cast<size_t>(1));
584 EXPECT_STREQ(locales[0]->language_code,
"C");
585 EXPECT_STREQ(locales[0]->country_code,
nullptr);
586 EXPECT_STREQ(locales[0]->script_code,
nullptr);
587 EXPECT_STREQ(locales[0]->variant_code,
nullptr);
594 EXPECT_EQ(
error,
nullptr);
598 if (initial_language) {
599 g_setenv(
"LANGUAGE", initial_language,
TRUE);
601 g_unsetenv(
"LANGUAGE");
605TEST(FlEngineTest, DuplicateLocale) {
606 g_autofree gchar* initial_language = g_strdup(g_getenv(
"LANGUAGE"));
607 g_setenv(
"LANGUAGE",
"en:en",
TRUE);
615 size_t locales_count) {
618 EXPECT_EQ(locales_count,
static_cast<size_t>(2));
620 EXPECT_STREQ(locales[0]->language_code,
"en");
621 EXPECT_STREQ(locales[0]->country_code,
nullptr);
622 EXPECT_STREQ(locales[0]->script_code,
nullptr);
623 EXPECT_STREQ(locales[0]->variant_code,
nullptr);
625 EXPECT_STREQ(locales[1]->language_code,
"C");
626 EXPECT_STREQ(locales[1]->country_code,
nullptr);
627 EXPECT_STREQ(locales[1]->script_code,
nullptr);
628 EXPECT_STREQ(locales[1]->variant_code,
nullptr);
635 EXPECT_EQ(
error,
nullptr);
639 if (initial_language) {
640 g_setenv(
"LANGUAGE", initial_language,
TRUE);
642 g_unsetenv(
"LANGUAGE");
646TEST(FlEngineTest, EmptyLocales) {
647 g_autofree gchar* initial_language = g_strdup(g_getenv(
"LANGUAGE"));
648 g_setenv(
"LANGUAGE",
"de:: :en_US",
TRUE);
656 size_t locales_count) {
659 EXPECT_EQ(locales_count,
static_cast<size_t>(4));
661 EXPECT_STREQ(locales[0]->language_code,
"de");
662 EXPECT_STREQ(locales[0]->country_code,
nullptr);
663 EXPECT_STREQ(locales[0]->script_code,
nullptr);
664 EXPECT_STREQ(locales[0]->variant_code,
nullptr);
666 EXPECT_STREQ(locales[1]->language_code,
"en");
667 EXPECT_STREQ(locales[1]->country_code,
"US");
668 EXPECT_STREQ(locales[1]->script_code,
nullptr);
669 EXPECT_STREQ(locales[1]->variant_code,
nullptr);
671 EXPECT_STREQ(locales[2]->language_code,
"en");
672 EXPECT_STREQ(locales[2]->country_code,
nullptr);
673 EXPECT_STREQ(locales[2]->script_code,
nullptr);
674 EXPECT_STREQ(locales[2]->variant_code,
nullptr);
676 EXPECT_STREQ(locales[3]->language_code,
"C");
677 EXPECT_STREQ(locales[3]->country_code,
nullptr);
678 EXPECT_STREQ(locales[3]->script_code,
nullptr);
679 EXPECT_STREQ(locales[3]->variant_code,
nullptr);
686 EXPECT_EQ(
error,
nullptr);
690 if (initial_language) {
691 g_setenv(
"LANGUAGE", initial_language,
TRUE);
693 g_unsetenv(
"LANGUAGE");
698 GAsyncResult* result,
703 EXPECT_EQ(
error,
nullptr);
705 g_main_loop_quit(
static_cast<GMainLoop*
>(
user_data));
709 g_autoptr(GMainLoop) loop = g_main_loop_new(
nullptr, 0);
731 g_autoptr(FlMockRenderable) renderable = fl_mock_renderable_new();
739 g_main_loop_run(loop);
743 GAsyncResult* result,
748 EXPECT_NE(
error,
nullptr);
750 g_main_loop_quit(
static_cast<GMainLoop*
>(
user_data));
753TEST(FlEngineTest, AddViewError) {
754 g_autoptr(GMainLoop) loop = g_main_loop_new(
nullptr, 0);
763 result.
added =
false;
770 g_autoptr(FlMockRenderable) renderable = fl_mock_renderable_new();
777 g_main_loop_run(loop);
781 GAsyncResult* result,
786 EXPECT_NE(
error,
nullptr);
788 g_main_loop_quit(
static_cast<GMainLoop*
>(
user_data));
791TEST(FlEngineTest, AddViewEngineError) {
792 g_autoptr(GMainLoop) loop = g_main_loop_new(
nullptr, 0);
802 g_autoptr(FlMockRenderable) renderable = fl_mock_renderable_new();
809 g_main_loop_run(loop);
813 GAsyncResult* result,
818 EXPECT_EQ(
error,
nullptr);
820 g_main_loop_quit(
static_cast<GMainLoop*
>(
user_data));
823TEST(FlEngineTest, RemoveView) {
824 g_autoptr(GMainLoop) loop = g_main_loop_new(
nullptr, 0);
848 g_main_loop_run(loop);
852 GAsyncResult* result,
857 EXPECT_NE(
error,
nullptr);
859 g_main_loop_quit(
static_cast<GMainLoop*
>(
user_data));
862TEST(FlEngineTest, RemoveViewError) {
863 g_autoptr(GMainLoop) loop = g_main_loop_new(
nullptr, 0);
882 g_main_loop_run(loop);
886 GAsyncResult* result,
891 EXPECT_NE(
error,
nullptr);
893 g_main_loop_quit(
static_cast<GMainLoop*
>(
user_data));
896TEST(FlEngineTest, RemoveViewEngineError) {
897 g_autoptr(GMainLoop) loop = g_main_loop_new(
nullptr, 0);
911 g_main_loop_run(loop);
914TEST(FlEngineTest, SendKeyEvent) {
915 g_autoptr(GMainLoop) loop = g_main_loop_new(
nullptr, 0);
922 EXPECT_EQ(
error,
nullptr);
932 EXPECT_EQ(event->
physical,
static_cast<uint64_t
>(42));
933 EXPECT_EQ(event->
logical,
static_cast<uint64_t
>(123));
950 [](GObject*
object, GAsyncResult* result, gpointer
user_data) {
955 EXPECT_EQ(
error,
nullptr);
956 EXPECT_TRUE(handled);
957 g_main_loop_quit(
static_cast<GMainLoop*
>(
user_data));
961 g_main_loop_run(loop);
965TEST(FlEngineTest, SendKeyEventNotHandled) {
966 g_autoptr(GMainLoop) loop = g_main_loop_new(
nullptr, 0);
973 EXPECT_EQ(
error,
nullptr);
995 [](GObject*
object, GAsyncResult* result, gpointer
user_data) {
1000 EXPECT_EQ(
error,
nullptr);
1001 EXPECT_FALSE(handled);
1002 g_main_loop_quit(
static_cast<GMainLoop*
>(
user_data));
1006 g_main_loop_run(loop);
1007 EXPECT_TRUE(called);
1010TEST(FlEngineTest, SendKeyEventError) {
1011 g_autoptr(GMainLoop) loop = g_main_loop_new(
nullptr, 0);
1019 EXPECT_EQ(
error,
nullptr);
1036 .synthesized =
true,
1040 [](GObject*
object, GAsyncResult* result, gpointer
user_data) {
1045 EXPECT_NE(
error,
nullptr);
1046 EXPECT_STREQ(
error->message,
"Failed to send key event");
1047 g_main_loop_quit(
static_cast<GMainLoop*
>(
user_data));
1051 g_main_loop_run(loop);
1052 EXPECT_TRUE(called);
#define FLUTTER_API_SYMBOL(symbol)
@ kFlutterKeyEventDeviceTypeKeyboard
@ kPanZoomUpdate
The pan/zoom updated.
FlutterEngineResult(* FlutterEngineSendPlatformMessageFnPtr)(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterPlatformMessage *message)
@ kFlutterPointerButtonMouseSecondary
@ kFlutterPointerSignalKindScroll
@ kFlutterPointerSignalKindNone
FlutterEngineDisplaysUpdateType
@ kFlutterEngineDisplaysUpdateTypeStartup
@ kFlutterSemanticsActionTap
void(* FlutterKeyEventCallback)(bool, void *)
@ kFlutterPointerDeviceKindTrackpad
@ kFlutterPointerDeviceKindMouse
void(* OnPreEngineRestartCallback)(void *)
g_autoptr(GMutexLocker) locker
G_MODULE_EXPORT void fl_dart_project_set_ui_thread_policy(FlDartProject *project, FlUIThreadPolicy policy)
G_MODULE_EXPORT void fl_dart_project_set_dart_entrypoint_arguments(FlDartProject *self, char **argv)
G_MODULE_EXPORT FlDartProject * fl_dart_project_new()
@ FL_UI_THREAD_POLICY_RUN_ON_PLATFORM_THREAD
@ FL_UI_THREAD_POLICY_RUN_ON_SEPARATE_THREAD
@ FL_UI_THREAD_POLICY_DEFAULT
FlTaskRunner * fl_engine_get_task_runner(FlEngine *self)
void fl_engine_send_mouse_pointer_event(FlEngine *self, FlutterViewId view_id, FlutterPointerPhase phase, size_t timestamp, double x, double y, FlutterPointerDeviceKind device_kind, double scroll_delta_x, double scroll_delta_y, int64_t buttons)
gboolean fl_engine_send_key_event_finish(FlEngine *self, GAsyncResult *result, gboolean *handled, GError **error)
void fl_engine_dispatch_semantics_action(FlEngine *self, FlutterViewId view_id, uint64_t node_id, FlutterSemanticsAction action, GBytes *data)
FlWindowingHandler * fl_engine_get_windowing_handler(FlEngine *self)
void fl_engine_notify_display_update(FlEngine *self, const FlutterEngineDisplay *displays, size_t displays_length)
void fl_engine_send_window_metrics_event(FlEngine *self, FlutterEngineDisplayId display_id, FlutterViewId view_id, size_t width, size_t height, double pixel_ratio)
FlMouseCursorHandler * fl_engine_get_mouse_cursor_handler(FlEngine *self)
gboolean fl_engine_remove_view_finish(FlEngine *self, GAsyncResult *result, GError **error)
FlDisplayMonitor * fl_engine_get_display_monitor(FlEngine *self)
gboolean fl_engine_send_platform_message_response(FlEngine *self, const FlutterPlatformMessageResponseHandle *handle, GBytes *response, GError **error)
void fl_engine_send_platform_message(FlEngine *self, const gchar *channel, GBytes *message, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
G_MODULE_EXPORT FlEngine * fl_engine_new(FlDartProject *project)
FlEngine * fl_engine_for_id(int64_t id)
void fl_engine_remove_view(FlEngine *self, FlutterViewId view_id, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
gboolean fl_engine_add_view_finish(FlEngine *self, GAsyncResult *result, GError **error)
void fl_engine_send_key_event(FlEngine *self, const FlutterKeyEvent *event, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
void fl_engine_send_pointer_pan_zoom_event(FlEngine *self, FlutterViewId view_id, size_t timestamp, double x, double y, FlutterPointerPhase phase, double pan_x, double pan_y, double scale, double rotation)
FlutterViewId fl_engine_add_view(FlEngine *self, FlRenderable *renderable, size_t width, size_t height, double pixel_ratio, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
FlutterEngineProcTable * fl_engine_get_embedder_api(FlEngine *self)
FlKeyboardManager * fl_engine_get_keyboard_manager(FlEngine *self)
G_MODULE_EXPORT FlBinaryMessenger * fl_engine_get_binary_messenger(FlEngine *self)
gboolean fl_engine_start(FlEngine *self, GError **error)
void on_pre_engine_restart_cb(FlEngine *engine, gpointer user_data)
static void remove_view_engine_error_cb(GObject *object, GAsyncResult *result, gpointer user_data)
TEST(FlEngineTest, NotifyDisplayUpdate)
static void remove_view_cb(GObject *object, GAsyncResult *result, gpointer user_data)
static void add_view_error_cb(GObject *object, GAsyncResult *result, gpointer user_data)
static void add_view_engine_error_cb(GObject *object, GAsyncResult *result, gpointer user_data)
static void remove_view_error_cb(GObject *object, GAsyncResult *result, gpointer user_data)
static void add_view_cb(GObject *object, GAsyncResult *result, gpointer user_data)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
G_MODULE_EXPORT FlJsonMessageCodec * fl_json_message_codec_new()
G_MODULE_EXPORT FlValue * fl_message_codec_decode_message(FlMessageCodec *self, GBytes *message, GError **error)
G_BEGIN_DECLS GBytes * message
const uint8_t uint32_t uint32_t GError ** error
G_MODULE_EXPORT FlValue * fl_value_lookup_string(FlValue *self, const gchar *key)
G_MODULE_EXPORT FlValueType fl_value_get_type(FlValue *self)
typedefG_BEGIN_DECLS struct _FlValue FlValue
G_BEGIN_DECLS FlutterViewId view_id
FlutterDesktopBinaryReply callback
#define MOCK_ENGINE_PROC(proc, mock_impl)
FlutterAddViewCallback add_view_callback
const FlutterWindowMetricsEvent * view_metrics
void * user_data
The |FlutterAddViewInfo.user_data|.
bool added
True if the add view operation succeeded.
size_t struct_size
The size of this struct. Must be sizeof(FlutterEngineDisplay).
FlutterEngineUpdateLocalesFnPtr UpdateLocales
FlutterEngineAddViewFnPtr AddView
FlutterEngineRemoveViewFnPtr RemoveView
FlutterEngineSendKeyEventFnPtr SendKeyEvent
FlutterEngineSendWindowMetricsEventFnPtr SendWindowMetricsEvent
FlutterEngineSendPointerEventFnPtr SendPointerEvent
FlutterEngineInitializeFnPtr Initialize
FlutterEngineNotifyDisplayUpdateFnPtr NotifyDisplayUpdate
FlutterEngineSendPlatformMessageFnPtr SendPlatformMessage
FlutterEngineRunInitializedFnPtr RunInitialized
FlutterEngineSendPlatformMessageResponseFnPtr SendPlatformMessageResponse
FlutterEngineSendSemanticsActionFnPtr SendSemanticsAction
size_t struct_size
The size of this struct. Must be sizeof(FlutterKeyEvent).
FlutterKeyEventDeviceType device_type
The source device for the key event.
FlutterKeyEventType type
The event kind.
FlutterRemoveViewCallback remove_view_callback
void * user_data
The |FlutterRemoveViewInfo.user_data|.
bool removed
True if the remove view operation succeeded.
FlutterViewId view_id
The ID of the view that includes the node.
FlutterSemanticsAction action
The semantics action.
size_t data_length
The data length.
uint64_t node_id
The semantics node identifier.
const uint8_t * data
Data associated with the action.
FlutterEngineDisplayId display_id
The identifier of the display the view is rendering on.
size_t height
Physical height of the window.
int64_t view_id
The view that this event is describing.
double pixel_ratio
Scale factor for the physical screen.
size_t width
Physical width of the window.
std::shared_ptr< const fml::Mapping > data