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, 800u);
92 EXPECT_EQ(event->
height, 600u);
109TEST(FlEngineTest, MousePointer) {
117 size_t events_count) {
119 EXPECT_EQ(events_count,
static_cast<size_t>(1));
120 EXPECT_EQ(events[0].
view_id, 1);
121 EXPECT_EQ(events[0].phase,
kDown);
122 EXPECT_EQ(events[0].timestamp,
static_cast<size_t>(1234567890));
123 EXPECT_EQ(events[0].
x, 800);
124 EXPECT_EQ(events[0].
y, 600);
125 EXPECT_EQ(events[0].
device,
static_cast<int32_t
>(0));
127 EXPECT_EQ(events[0].scroll_delta_x, 1.2);
128 EXPECT_EQ(events[0].scroll_delta_y, -3.4);
137 EXPECT_EQ(
error,
nullptr);
146TEST(FlEngineTest, PointerPanZoom) {
154 size_t events_count) {
156 EXPECT_EQ(events_count,
static_cast<size_t>(1));
157 EXPECT_EQ(events[0].
view_id, 1);
159 EXPECT_EQ(events[0].timestamp,
static_cast<size_t>(1234567890));
160 EXPECT_EQ(events[0].
x, 800);
161 EXPECT_EQ(events[0].
y, 600);
162 EXPECT_EQ(events[0].
device,
static_cast<int32_t
>(1));
164 EXPECT_EQ(events[0].pan_x, 1.5);
165 EXPECT_EQ(events[0].pan_y, 2.5);
166 EXPECT_EQ(events[0].scale, 3.5);
167 EXPECT_EQ(events[0].rotation, 4.5);
169 EXPECT_EQ(events[0].buttons, 0);
176 EXPECT_EQ(
error,
nullptr);
184TEST(FlEngineTest, DispatchSemanticsAction) {
192 EXPECT_EQ(info->
view_id,
static_cast<int64_t
>(456));
193 EXPECT_EQ(info->
node_id,
static_cast<uint64_t
>(42));
195 EXPECT_EQ(info->
data_length,
static_cast<size_t>(4));
196 EXPECT_EQ(info->
data[0],
't');
197 EXPECT_EQ(info->
data[1],
'e');
198 EXPECT_EQ(info->
data[2],
's');
199 EXPECT_EQ(info->
data[3],
't');
207 EXPECT_EQ(
error,
nullptr);
208 g_autoptr(GBytes) data = g_bytes_new_static(
"test", 4);
225 ([&called, old_handler](
auto engine,
227 if (strcmp(
message->channel,
"test") != 0) {
228 return old_handler(engine, message);
233 EXPECT_EQ(
message->message_size,
static_cast<size_t>(4));
234 EXPECT_EQ(
message->message[0],
't');
235 EXPECT_EQ(
message->message[1],
'e');
236 EXPECT_EQ(
message->message[2],
's');
237 EXPECT_EQ(
message->message[3],
't');
244 EXPECT_EQ(
error,
nullptr);
260 SendPlatformMessageResponse,
263 const uint8_t* data,
size_t data_length) {
270 EXPECT_EQ(data_length,
static_cast<size_t>(4));
271 EXPECT_EQ(data[0],
't');
272 EXPECT_EQ(data[1],
'e');
273 EXPECT_EQ(data[2],
's');
274 EXPECT_EQ(data[3],
't');
281 EXPECT_EQ(
error,
nullptr);
282 g_autoptr(GBytes) response = g_bytes_new_static(
"test", 4);
286 EXPECT_EQ(
error,
nullptr);
292TEST(FlEngineTest, SettingsHandler) {
302 EXPECT_STREQ(
message->channel,
"flutter/settings");
309 FL_MESSAGE_CODEC(codec), data, &
error);
310 EXPECT_NE(settings,
nullptr);
311 EXPECT_EQ(
error,
nullptr);
315 EXPECT_NE(text_scale_factor,
nullptr);
318 FlValue* always_use_24hr_format =
320 EXPECT_NE(always_use_24hr_format,
nullptr);
326 EXPECT_NE(platform_brightness,
nullptr);
334 EXPECT_EQ(
error,
nullptr);
340 int* count =
reinterpret_cast<int*
>(
user_data);
345TEST(FlEngineTest, OnPreEngineRestart) {
350 void* callback_user_data;
354 Initialize, ([&
callback, &callback_user_data, &called](
369 EXPECT_EQ(
error,
nullptr);
383 g_signal_connect(
engine,
"on-pre-engine-restart",
390TEST(FlEngineTest, DartEntrypointArgs) {
391 GPtrArray* args_array = g_ptr_array_new();
392 g_ptr_array_add(args_array,
const_cast<char*
>(
"arg_one"));
393 g_ptr_array_add(args_array,
const_cast<char*
>(
"arg_two"));
394 g_ptr_array_add(args_array,
const_cast<char*
>(
"arg_three"));
395 g_ptr_array_add(args_array,
nullptr);
396 gchar**
args =
reinterpret_cast<gchar**
>(g_ptr_array_free(args_array,
false));
404 Initialize, ([&called, &set_args =
args](
409 EXPECT_NE(set_args,
args->dart_entrypoint_argv);
410 EXPECT_EQ(
args->dart_entrypoint_argc, 3);
419 EXPECT_EQ(
error,
nullptr);
433 engine_id =
args->engine_id;
441 EXPECT_EQ(
error,
nullptr);
442 EXPECT_TRUE(engine_id != 0);
447TEST(FlEngineTest, UIIsolateDefaultThreadPolicy) {
452 bool same_task_runner =
false;
459 same_task_runner =
args->custom_task_runners->platform_task_runner ==
460 args->custom_task_runners->ui_task_runner;
468 EXPECT_EQ(
error,
nullptr);
469 EXPECT_TRUE(same_task_runner);
472TEST(FlEngineTest, UIIsolateOnPlatformTaskRunner) {
478 bool same_task_runner =
false;
485 same_task_runner =
args->custom_task_runners->platform_task_runner ==
486 args->custom_task_runners->ui_task_runner;
494 EXPECT_EQ(
error,
nullptr);
495 EXPECT_TRUE(same_task_runner);
498TEST(FlEngineTest, UIIsolateOnSeparateThread) {
504 bool separate_thread =
false;
511 separate_thread =
args->custom_task_runners->ui_task_runner ==
nullptr;
519 EXPECT_EQ(
error,
nullptr);
520 EXPECT_TRUE(separate_thread);
524 g_autofree gchar* initial_language = g_strdup(g_getenv(
"LANGUAGE"));
525 g_setenv(
"LANGUAGE",
"de:en_US",
TRUE);
533 size_t locales_count) {
536 EXPECT_EQ(locales_count,
static_cast<size_t>(4));
538 EXPECT_STREQ(locales[0]->language_code,
"de");
539 EXPECT_STREQ(locales[0]->country_code,
nullptr);
540 EXPECT_STREQ(locales[0]->script_code,
nullptr);
541 EXPECT_STREQ(locales[0]->variant_code,
nullptr);
543 EXPECT_STREQ(locales[1]->language_code,
"en");
544 EXPECT_STREQ(locales[1]->country_code,
"US");
545 EXPECT_STREQ(locales[1]->script_code,
nullptr);
546 EXPECT_STREQ(locales[1]->variant_code,
nullptr);
548 EXPECT_STREQ(locales[2]->language_code,
"en");
549 EXPECT_STREQ(locales[2]->country_code,
nullptr);
550 EXPECT_STREQ(locales[2]->script_code,
nullptr);
551 EXPECT_STREQ(locales[2]->variant_code,
nullptr);
553 EXPECT_STREQ(locales[3]->language_code,
"C");
554 EXPECT_STREQ(locales[3]->country_code,
nullptr);
555 EXPECT_STREQ(locales[3]->script_code,
nullptr);
556 EXPECT_STREQ(locales[3]->variant_code,
nullptr);
563 EXPECT_EQ(
error,
nullptr);
567 if (initial_language) {
568 g_setenv(
"LANGUAGE", initial_language,
TRUE);
570 g_unsetenv(
"LANGUAGE");
575 g_autofree gchar* initial_language = g_strdup(g_getenv(
"LANGUAGE"));
576 g_setenv(
"LANGUAGE",
"C",
TRUE);
584 size_t locales_count) {
587 EXPECT_EQ(locales_count,
static_cast<size_t>(1));
589 EXPECT_STREQ(locales[0]->language_code,
"C");
590 EXPECT_STREQ(locales[0]->country_code,
nullptr);
591 EXPECT_STREQ(locales[0]->script_code,
nullptr);
592 EXPECT_STREQ(locales[0]->variant_code,
nullptr);
599 EXPECT_EQ(
error,
nullptr);
603 if (initial_language) {
604 g_setenv(
"LANGUAGE", initial_language,
TRUE);
606 g_unsetenv(
"LANGUAGE");
610TEST(FlEngineTest, DuplicateLocale) {
611 g_autofree gchar* initial_language = g_strdup(g_getenv(
"LANGUAGE"));
612 g_setenv(
"LANGUAGE",
"en:en",
TRUE);
620 size_t locales_count) {
623 EXPECT_EQ(locales_count,
static_cast<size_t>(2));
625 EXPECT_STREQ(locales[0]->language_code,
"en");
626 EXPECT_STREQ(locales[0]->country_code,
nullptr);
627 EXPECT_STREQ(locales[0]->script_code,
nullptr);
628 EXPECT_STREQ(locales[0]->variant_code,
nullptr);
630 EXPECT_STREQ(locales[1]->language_code,
"C");
631 EXPECT_STREQ(locales[1]->country_code,
nullptr);
632 EXPECT_STREQ(locales[1]->script_code,
nullptr);
633 EXPECT_STREQ(locales[1]->variant_code,
nullptr);
640 EXPECT_EQ(
error,
nullptr);
644 if (initial_language) {
645 g_setenv(
"LANGUAGE", initial_language,
TRUE);
647 g_unsetenv(
"LANGUAGE");
651TEST(FlEngineTest, EmptyLocales) {
652 g_autofree gchar* initial_language = g_strdup(g_getenv(
"LANGUAGE"));
653 g_setenv(
"LANGUAGE",
"de:: :en_US",
TRUE);
661 size_t locales_count) {
664 EXPECT_EQ(locales_count,
static_cast<size_t>(4));
666 EXPECT_STREQ(locales[0]->language_code,
"de");
667 EXPECT_STREQ(locales[0]->country_code,
nullptr);
668 EXPECT_STREQ(locales[0]->script_code,
nullptr);
669 EXPECT_STREQ(locales[0]->variant_code,
nullptr);
671 EXPECT_STREQ(locales[1]->language_code,
"en");
672 EXPECT_STREQ(locales[1]->country_code,
"US");
673 EXPECT_STREQ(locales[1]->script_code,
nullptr);
674 EXPECT_STREQ(locales[1]->variant_code,
nullptr);
676 EXPECT_STREQ(locales[2]->language_code,
"en");
677 EXPECT_STREQ(locales[2]->country_code,
nullptr);
678 EXPECT_STREQ(locales[2]->script_code,
nullptr);
679 EXPECT_STREQ(locales[2]->variant_code,
nullptr);
681 EXPECT_STREQ(locales[3]->language_code,
"C");
682 EXPECT_STREQ(locales[3]->country_code,
nullptr);
683 EXPECT_STREQ(locales[3]->script_code,
nullptr);
684 EXPECT_STREQ(locales[3]->variant_code,
nullptr);
691 EXPECT_EQ(
error,
nullptr);
695 if (initial_language) {
696 g_setenv(
"LANGUAGE", initial_language,
TRUE);
698 g_unsetenv(
"LANGUAGE");
703 GAsyncResult* result,
708 EXPECT_EQ(
error,
nullptr);
710 g_main_loop_quit(
static_cast<GMainLoop*
>(
user_data));
714 g_autoptr(GMainLoop) loop = g_main_loop_new(
nullptr, 0);
749 g_main_loop_run(loop);
753 GAsyncResult* result,
758 EXPECT_NE(
error,
nullptr);
760 g_main_loop_quit(
static_cast<GMainLoop*
>(
user_data));
763TEST(FlEngineTest, AddViewError) {
764 g_autoptr(GMainLoop) loop = g_main_loop_new(
nullptr, 0);
773 result.
added =
false;
787 g_main_loop_run(loop);
791 GAsyncResult* result,
796 EXPECT_NE(
error,
nullptr);
798 g_main_loop_quit(
static_cast<GMainLoop*
>(
user_data));
801TEST(FlEngineTest, AddViewEngineError) {
802 g_autoptr(GMainLoop) loop = g_main_loop_new(
nullptr, 0);
819 g_main_loop_run(loop);
823 GAsyncResult* result,
828 EXPECT_EQ(
error,
nullptr);
830 g_main_loop_quit(
static_cast<GMainLoop*
>(
user_data));
833TEST(FlEngineTest, RemoveView) {
834 g_autoptr(GMainLoop) loop = g_main_loop_new(
nullptr, 0);
858 g_main_loop_run(loop);
862 GAsyncResult* result,
867 EXPECT_NE(
error,
nullptr);
869 g_main_loop_quit(
static_cast<GMainLoop*
>(
user_data));
872TEST(FlEngineTest, RemoveViewError) {
873 g_autoptr(GMainLoop) loop = g_main_loop_new(
nullptr, 0);
892 g_main_loop_run(loop);
896 GAsyncResult* result,
901 EXPECT_NE(
error,
nullptr);
903 g_main_loop_quit(
static_cast<GMainLoop*
>(
user_data));
906TEST(FlEngineTest, RemoveViewEngineError) {
907 g_autoptr(GMainLoop) loop = g_main_loop_new(
nullptr, 0);
921 g_main_loop_run(loop);
924TEST(FlEngineTest, SendKeyEvent) {
925 g_autoptr(GMainLoop) loop = g_main_loop_new(
nullptr, 0);
932 EXPECT_EQ(
error,
nullptr);
942 EXPECT_EQ(event->
physical,
static_cast<uint64_t
>(42));
943 EXPECT_EQ(event->
logical,
static_cast<uint64_t
>(123));
960 [](GObject*
object, GAsyncResult* result, gpointer
user_data) {
965 EXPECT_EQ(
error,
nullptr);
966 EXPECT_TRUE(handled);
967 g_main_loop_quit(
static_cast<GMainLoop*
>(
user_data));
971 g_main_loop_run(loop);
975TEST(FlEngineTest, SendKeyEventNotHandled) {
976 g_autoptr(GMainLoop) loop = g_main_loop_new(
nullptr, 0);
983 EXPECT_EQ(
error,
nullptr);
1001 .synthesized =
true,
1005 [](GObject*
object, GAsyncResult* result, gpointer
user_data) {
1010 EXPECT_EQ(
error,
nullptr);
1011 EXPECT_FALSE(handled);
1012 g_main_loop_quit(
static_cast<GMainLoop*
>(
user_data));
1016 g_main_loop_run(loop);
1017 EXPECT_TRUE(called);
1020TEST(FlEngineTest, SendKeyEventError) {
1021 g_autoptr(GMainLoop) loop = g_main_loop_new(
nullptr, 0);
1029 EXPECT_EQ(
error,
nullptr);
1046 .synthesized =
true,
1050 [](GObject*
object, GAsyncResult* result, gpointer
user_data) {
1055 EXPECT_NE(
error,
nullptr);
1056 EXPECT_STREQ(
error->message,
"Failed to send key event");
1057 g_main_loop_quit(
static_cast<GMainLoop*
>(
user_data));
1061 g_main_loop_run(loop);
1062 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(FlEngine) engine
FlRenderable * renderable
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)
void fl_engine_send_window_metrics_event(FlEngine *self, FlutterEngineDisplayId display_id, FlutterViewId view_id, size_t min_width, size_t min_height, size_t max_width, size_t max_height, double pixel_ratio)
void fl_engine_notify_display_update(FlEngine *self, const FlutterEngineDisplay *displays, size_t displays_length)
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)
FlutterViewId fl_engine_add_view(FlEngine *self, FlRenderable *renderable, size_t min_width, size_t min_height, size_t max_width, size_t max_height, double pixel_ratio, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
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)
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)
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)
impeller::ShaderType type
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.
size_t min_height_constraint
size_t min_width_constraint
int64_t view_id
The view that this event is describing.
double pixel_ratio
Scale factor for the physical screen.
size_t max_width_constraint
size_t max_height_constraint
size_t width
Physical width of the window.