6#include "gtest/gtest.h"
8#include "flutter/shell/platform/common/app_lifecycle_state.h"
9#include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h"
10#include "flutter/shell/platform/linux/fl_engine_private.h"
11#include "flutter/shell/platform/linux/public/flutter_linux/fl_engine.h"
12#include "flutter/shell/platform/linux/public/flutter_linux/fl_json_message_codec.h"
13#include "flutter/shell/platform/linux/public/flutter_linux/fl_string_codec.h"
14#include "flutter/shell/platform/linux/testing/fl_test.h"
20TEST(FlEngineTest, WindowMetrics) {
26 SendWindowMetricsEvent,
29 EXPECT_EQ(
event->width,
static_cast<size_t>(3840));
30 EXPECT_EQ(
event->height,
static_cast<size_t>(2160));
31 EXPECT_EQ(
event->pixel_ratio, 2.0);
36 g_autoptr(GError)
error =
nullptr;
38 EXPECT_EQ(
error,
nullptr);
45TEST(FlEngineTest, MousePointer) {
53 size_t events_count) {
55 EXPECT_EQ(events_count,
static_cast<size_t>(1));
56 EXPECT_EQ(events[0].phase,
kDown);
57 EXPECT_EQ(events[0].timestamp,
static_cast<size_t>(1234567890));
58 EXPECT_EQ(events[0].
x, 800);
59 EXPECT_EQ(events[0].
y, 600);
60 EXPECT_EQ(events[0].
device,
static_cast<int32_t
>(0));
62 EXPECT_EQ(events[0].scroll_delta_x, 1.2);
63 EXPECT_EQ(events[0].scroll_delta_y, -3.4);
70 g_autoptr(GError)
error =
nullptr;
72 EXPECT_EQ(
error,
nullptr);
80TEST(FlEngineTest, PointerPanZoom) {
88 size_t events_count) {
90 EXPECT_EQ(events_count,
static_cast<size_t>(1));
92 EXPECT_EQ(events[0].timestamp,
static_cast<size_t>(1234567890));
93 EXPECT_EQ(events[0].
x, 800);
94 EXPECT_EQ(events[0].
y, 600);
95 EXPECT_EQ(events[0].
device,
static_cast<int32_t
>(1));
97 EXPECT_EQ(events[0].pan_x, 1.5);
98 EXPECT_EQ(events[0].pan_y, 2.5);
99 EXPECT_EQ(events[0].
scale, 3.5);
100 EXPECT_EQ(events[0].rotation, 4.5);
102 EXPECT_EQ(events[0].buttons, 0);
107 g_autoptr(GError)
error =
nullptr;
109 EXPECT_EQ(
error,
nullptr);
117TEST(FlEngineTest, DispatchSemanticsAction) {
123 DispatchSemanticsAction,
125 const uint8_t* data,
size_t data_length) {
126 EXPECT_EQ(
id,
static_cast<uint64_t
>(42));
128 EXPECT_EQ(data_length,
static_cast<size_t>(4));
129 EXPECT_EQ(data[0],
't');
130 EXPECT_EQ(data[1],
'e');
131 EXPECT_EQ(data[2],
's');
132 EXPECT_EQ(data[3],
't');
138 g_autoptr(GError)
error =
nullptr;
140 EXPECT_EQ(
error,
nullptr);
141 g_autoptr(GBytes) data = g_bytes_new_static(
"test", 4);
158 ([&called, old_handler](
auto engine,
160 if (strcmp(
message->channel,
"test") != 0) {
161 return old_handler(engine, message);
166 EXPECT_EQ(
message->message_size,
static_cast<size_t>(4));
167 EXPECT_EQ(
message->message[0],
't');
168 EXPECT_EQ(
message->message[1],
'e');
169 EXPECT_EQ(
message->message[2],
's');
170 EXPECT_EQ(
message->message[3],
't');
175 g_autoptr(GError)
error =
nullptr;
177 EXPECT_EQ(
error,
nullptr);
178 g_autoptr(GBytes)
message = g_bytes_new_static(
"test", 4);
192 SendPlatformMessageResponse,
195 const uint8_t* data,
size_t data_length) {
201 EXPECT_EQ(data_length,
static_cast<size_t>(4));
202 EXPECT_EQ(data[0],
't');
203 EXPECT_EQ(data[1],
'e');
204 EXPECT_EQ(data[2],
's');
205 EXPECT_EQ(data[3],
't');
210 g_autoptr(GError)
error =
nullptr;
212 EXPECT_EQ(
error,
nullptr);
213 g_autoptr(GBytes) response = g_bytes_new_static(
"test", 4);
217 EXPECT_EQ(
error,
nullptr);
223TEST(FlEngineTest, SettingsPlugin) {
233 EXPECT_STREQ(
message->channel,
"flutter/settings");
236 g_autoptr(GBytes) data =
238 g_autoptr(GError)
error =
nullptr;
240 FL_MESSAGE_CODEC(codec), data, &
error);
241 EXPECT_NE(settings,
nullptr);
242 EXPECT_EQ(
error,
nullptr);
246 EXPECT_NE(text_scale_factor,
nullptr);
249 FlValue* always_use_24hr_format =
251 EXPECT_NE(always_use_24hr_format,
nullptr);
257 EXPECT_NE(platform_brightness,
nullptr);
263 g_autoptr(GError)
error =
nullptr;
265 EXPECT_EQ(
error,
nullptr);
281TEST(FlEngineTest, OnPreEngineRestart) {
286 void* callback_user_data;
290 Initialize, ([&
callback, &callback_user_data, &called](
301 g_autoptr(GError)
error =
nullptr;
303 EXPECT_EQ(
error,
nullptr);
326 EXPECT_EQ(
count, 11);
329TEST(FlEngineTest, DartEntrypointArgs) {
332 GPtrArray* args_array = g_ptr_array_new();
333 g_ptr_array_add(args_array,
const_cast<char*
>(
"arg_one"));
334 g_ptr_array_add(args_array,
const_cast<char*
>(
"arg_two"));
335 g_ptr_array_add(args_array,
const_cast<char*
>(
"arg_three"));
336 g_ptr_array_add(args_array,
nullptr);
337 gchar**
args =
reinterpret_cast<gchar**
>(g_ptr_array_free(args_array,
false));
346 Initialize, ([&called, &set_args =
args](
351 EXPECT_NE(set_args,
args->dart_entrypoint_argv);
352 EXPECT_EQ(
args->dart_entrypoint_argc, 3);
357 g_autoptr(GError)
error =
nullptr;
359 EXPECT_EQ(
error,
nullptr);
365 gchar* initial_language = g_strdup(g_getenv(
"LANGUAGE"));
366 g_setenv(
"LANGUAGE",
"de:en_US",
TRUE);
375 size_t locales_count) {
378 EXPECT_EQ(locales_count,
static_cast<size_t>(4));
380 EXPECT_STREQ(locales[0]->language_code,
"de");
381 EXPECT_STREQ(locales[0]->country_code,
nullptr);
382 EXPECT_STREQ(locales[0]->script_code,
nullptr);
383 EXPECT_STREQ(locales[0]->variant_code,
nullptr);
385 EXPECT_STREQ(locales[1]->language_code,
"en");
386 EXPECT_STREQ(locales[1]->country_code,
"US");
387 EXPECT_STREQ(locales[1]->script_code,
nullptr);
388 EXPECT_STREQ(locales[1]->variant_code,
nullptr);
390 EXPECT_STREQ(locales[2]->language_code,
"en");
391 EXPECT_STREQ(locales[2]->country_code,
nullptr);
392 EXPECT_STREQ(locales[2]->script_code,
nullptr);
393 EXPECT_STREQ(locales[2]->variant_code,
nullptr);
395 EXPECT_STREQ(locales[3]->language_code,
"C");
396 EXPECT_STREQ(locales[3]->country_code,
nullptr);
397 EXPECT_STREQ(locales[3]->script_code,
nullptr);
398 EXPECT_STREQ(locales[3]->variant_code,
nullptr);
403 g_autoptr(GError)
error =
nullptr;
405 EXPECT_EQ(
error,
nullptr);
409 if (initial_language) {
410 g_setenv(
"LANGUAGE", initial_language,
TRUE);
412 g_unsetenv(
"LANGUAGE");
414 g_free(initial_language);
417TEST(FlEngineTest, SwitchesEmpty) {
421 unsetenv(
"FLUTTER_ENGINE_SWITCHES");
425 EXPECT_EQ(switches->len, 0U);
428TEST(FlEngineTest, SendWindowStateEvent) {
437 EXPECT_STREQ(
message->channel,
"flutter/lifecycle");
440 g_autoptr(GBytes) data =
442 g_autoptr(GError)
error =
nullptr;
444 FL_MESSAGE_CODEC(codec), data, &
error);
464#ifndef FLUTTER_RELEASE
468 setenv(
"FLUTTER_ENGINE_SWITCHES",
"2", 1);
469 setenv(
"FLUTTER_ENGINE_SWITCH_1",
"abc", 1);
470 setenv(
"FLUTTER_ENGINE_SWITCH_2",
"foo=\"bar, baz\"", 1);
473 EXPECT_EQ(switches->len, 2U);
474 EXPECT_STREQ(
static_cast<const char*
>(g_ptr_array_index(switches, 0)),
476 EXPECT_STREQ(
static_cast<const char*
>(g_ptr_array_index(switches, 1)),
477 "--foo=\"bar, baz\"");
479 unsetenv(
"FLUTTER_ENGINE_SWITCHES");
480 unsetenv(
"FLUTTER_ENGINE_SWITCH_1");
481 unsetenv(
"FLUTTER_ENGINE_SWITCH_2");
#define TEST(S, s, D, expected)
#define FLUTTER_API_SYMBOL(symbol)
@ kPanZoomUpdate
The pan/zoom updated.
FlutterEngineResult(* FlutterEngineSendPlatformMessageFnPtr)(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterPlatformMessage *message)
@ kFlutterPointerButtonMouseSecondary
@ kFlutterPointerSignalKindScroll
@ kFlutterPointerSignalKindNone
@ kFlutterSemanticsActionTap
@ kFlutterPointerDeviceKindTrackpad
@ kFlutterPointerDeviceKindMouse
void(* OnPreEngineRestartCallback)(void *)
G_MODULE_EXPORT void fl_dart_project_set_dart_entrypoint_arguments(FlDartProject *self, char **argv)
G_MODULE_EXPORT FlDartProject * fl_dart_project_new()
void fl_engine_send_pointer_pan_zoom_event(FlEngine *self, size_t timestamp, double x, double y, FlutterPointerPhase phase, double pan_x, double pan_y, double scale, double rotation)
gboolean fl_engine_send_platform_message_response(FlEngine *self, const FlutterPlatformMessageResponseHandle *handle, GBytes *response, GError **error)
void fl_engine_set_on_pre_engine_restart_handler(FlEngine *self, FlEngineOnPreEngineRestartHandler handler, gpointer user_data, GDestroyNotify destroy_notify)
void fl_engine_send_platform_message(FlEngine *self, const gchar *channel, GBytes *message, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
void fl_engine_dispatch_semantics_action(FlEngine *self, uint64_t id, FlutterSemanticsAction action, GBytes *data)
GPtrArray * fl_engine_get_switches(FlEngine *self)
void fl_engine_send_window_state_event(FlEngine *self, gboolean visible, gboolean focused)
void fl_engine_send_mouse_pointer_event(FlEngine *self, FlutterPointerPhase phase, size_t timestamp, double x, double y, double scroll_delta_x, double scroll_delta_y, int64_t buttons)
FlutterEngineProcTable * fl_engine_get_embedder_api(FlEngine *self)
void fl_engine_send_window_metrics_event(FlEngine *self, size_t width, size_t height, double pixel_ratio)
gboolean fl_engine_start(FlEngine *self, GError **error)
void on_pre_engine_restart_cb(FlEngine *engine, gpointer user_data)
void on_pre_engine_restart_destroy_notify(gpointer user_data)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
static FlEngine * make_mock_engine()
G_MODULE_EXPORT FlJsonMessageCodec * fl_json_message_codec_new()
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
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 FlStringCodec * fl_string_codec_new()
FlEngine * make_mock_engine_with_project(FlDartProject *project)
G_MODULE_EXPORT FlValue * fl_value_lookup_string(FlValue *self, const gchar *key)
G_MODULE_EXPORT FlValueType fl_value_get_type(FlValue *self)
G_MODULE_EXPORT const gchar * fl_value_get_string(FlValue *self)
typedefG_BEGIN_DECLS struct _FlValue FlValue
constexpr const char * AppLifecycleStateToString(AppLifecycleState state)
#define MOCK_ENGINE_PROC(proc, mock_impl)
Function-pointer-based versions of the APIs above.
FlutterEngineUpdateLocalesFnPtr UpdateLocales
FlutterEngineSendWindowMetricsEventFnPtr SendWindowMetricsEvent
FlutterEngineSendPointerEventFnPtr SendPointerEvent
FlutterEngineInitializeFnPtr Initialize
FlutterEngineDispatchSemanticsActionFnPtr DispatchSemanticsAction
FlutterEngineSendPlatformMessageFnPtr SendPlatformMessage
FlutterEngineSendPlatformMessageResponseFnPtr SendPlatformMessageResponse
#define EXPECT_TRUE(handle)