Flutter Linux Embedder
fl_engine_test.cc File Reference
#include "gtest/gtest.h"
#include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h"
#include "flutter/shell/platform/linux/fl_engine_private.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_engine.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_json_message_codec.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_string_codec.h"
#include "flutter/shell/platform/linux/testing/fl_test.h"

Go to the source code of this file.

Functions

 TEST (FlEngineTest, WindowMetrics)
 
 TEST (FlEngineTest, MousePointer)
 
 TEST (FlEngineTest, PointerPanZoom)
 
 TEST (FlEngineTest, DispatchSemanticsAction)
 
 TEST (FlEngineTest, PlatformMessage)
 
 TEST (FlEngineTest, PlatformMessageResponse)
 
 TEST (FlEngineTest, SettingsHandler)
 
void on_pre_engine_restart_cb (FlEngine *engine, gpointer user_data)
 
 TEST (FlEngineTest, OnPreEngineRestart)
 
 TEST (FlEngineTest, DartEntrypointArgs)
 
 TEST (FlEngineTest, Locales)
 
 TEST (FlEngineTest, CLocale)
 
 TEST (FlEngineTest, DuplicateLocale)
 
 TEST (FlEngineTest, EmptyLocales)
 
 TEST (FlEngineTest, SwitchesEmpty)
 
static void add_view_cb (GObject *object, GAsyncResult *result, gpointer user_data)
 
 TEST (FlEngineTest, AddView)
 
static void add_view_error_cb (GObject *object, GAsyncResult *result, gpointer user_data)
 
 TEST (FlEngineTest, AddViewError)
 
static void add_view_engine_error_cb (GObject *object, GAsyncResult *result, gpointer user_data)
 
 TEST (FlEngineTest, AddViewEngineError)
 
static void remove_view_cb (GObject *object, GAsyncResult *result, gpointer user_data)
 
 TEST (FlEngineTest, RemoveView)
 
static void remove_view_error_cb (GObject *object, GAsyncResult *result, gpointer user_data)
 
 TEST (FlEngineTest, RemoveViewError)
 
static void remove_view_engine_error_cb (GObject *object, GAsyncResult *result, gpointer user_data)
 
 TEST (FlEngineTest, RemoveViewEngineError)
 
 TEST (FlEngineTest, Switches)
 

Function Documentation

◆ add_view_cb()

static void add_view_cb ( GObject *  object,
GAsyncResult *  result,
gpointer  user_data 
)
static

Definition at line 551 of file fl_engine_test.cc.

553  {
554  g_autoptr(GError) error = nullptr;
555  gboolean r = fl_engine_add_view_finish(FL_ENGINE(object), result, &error);
556  EXPECT_TRUE(r);
557  EXPECT_EQ(error, nullptr);
558 
559  g_main_loop_quit(static_cast<GMainLoop*>(user_data));
560 }

References error, fl_engine_add_view_finish(), result, and user_data.

Referenced by TEST().

◆ add_view_engine_error_cb()

static void add_view_engine_error_cb ( GObject *  object,
GAsyncResult *  result,
gpointer  user_data 
)
static

Definition at line 630 of file fl_engine_test.cc.

632  {
633  g_autoptr(GError) error = nullptr;
634  gboolean r = fl_engine_add_view_finish(FL_ENGINE(object), result, &error);
635  EXPECT_FALSE(r);
636  EXPECT_NE(error, nullptr);
637 
638  g_main_loop_quit(static_cast<GMainLoop*>(user_data));
639 }

References error, fl_engine_add_view_finish(), result, and user_data.

Referenced by TEST().

◆ add_view_error_cb()

static void add_view_error_cb ( GObject *  object,
GAsyncResult *  result,
gpointer  user_data 
)
static

Definition at line 594 of file fl_engine_test.cc.

596  {
597  g_autoptr(GError) error = nullptr;
598  gboolean r = fl_engine_add_view_finish(FL_ENGINE(object), result, &error);
599  EXPECT_FALSE(r);
600  EXPECT_NE(error, nullptr);
601 
602  g_main_loop_quit(static_cast<GMainLoop*>(user_data));
603 }

References error, fl_engine_add_view_finish(), result, and user_data.

Referenced by TEST().

◆ on_pre_engine_restart_cb()

void on_pre_engine_restart_cb ( FlEngine *  engine,
gpointer  user_data 
)

Definition at line 273 of file fl_engine_test.cc.

273  {
274  int* count = reinterpret_cast<int*>(user_data);
275  *count += 1;
276 }

References user_data.

Referenced by TEST().

◆ remove_view_cb()

static void remove_view_cb ( GObject *  object,
GAsyncResult *  result,
gpointer  user_data 
)
static

Definition at line 660 of file fl_engine_test.cc.

662  {
663  g_autoptr(GError) error = nullptr;
664  gboolean r = fl_engine_remove_view_finish(FL_ENGINE(object), result, &error);
665  EXPECT_TRUE(r);
666  EXPECT_EQ(error, nullptr);
667 
668  g_main_loop_quit(static_cast<GMainLoop*>(user_data));
669 }

References error, fl_engine_remove_view_finish(), result, and user_data.

Referenced by TEST().

◆ remove_view_engine_error_cb()

static void remove_view_engine_error_cb ( GObject *  object,
GAsyncResult *  result,
gpointer  user_data 
)
static

Definition at line 733 of file fl_engine_test.cc.

735  {
736  g_autoptr(GError) error = nullptr;
737  gboolean r = fl_engine_remove_view_finish(FL_ENGINE(object), result, &error);
738  EXPECT_FALSE(r);
739  EXPECT_NE(error, nullptr);
740 
741  g_main_loop_quit(static_cast<GMainLoop*>(user_data));
742 }

References error, fl_engine_remove_view_finish(), result, and user_data.

Referenced by TEST().

◆ remove_view_error_cb()

static void remove_view_error_cb ( GObject *  object,
GAsyncResult *  result,
gpointer  user_data 
)
static

Definition at line 699 of file fl_engine_test.cc.

701  {
702  g_autoptr(GError) error = nullptr;
703  gboolean r = fl_engine_remove_view_finish(FL_ENGINE(object), result, &error);
704  EXPECT_FALSE(r);
705  EXPECT_NE(error, nullptr);
706 
707  g_main_loop_quit(static_cast<GMainLoop*>(user_data));
708 }

References error, fl_engine_remove_view_finish(), result, and user_data.

Referenced by TEST().

◆ TEST() [1/21]

TEST ( FlEngineTest  ,
AddView   
)

Definition at line 562 of file fl_engine_test.cc.

562  {
563  g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
564 
565  g_autoptr(FlEngine) engine = make_mock_engine();
566  FlutterEngineProcTable* embedder_api = fl_engine_get_embedder_api(engine);
567 
568  bool called = false;
569  embedder_api->AddView = MOCK_ENGINE_PROC(
570  AddView, ([&called](auto engine, const FlutterAddViewInfo* info) {
571  called = true;
572  EXPECT_EQ(info->view_metrics->width, 123u);
573  EXPECT_EQ(info->view_metrics->height, 456u);
574  EXPECT_EQ(info->view_metrics->pixel_ratio, 2.0);
575 
576  FlutterAddViewResult result;
577  result.struct_size = sizeof(FlutterAddViewResult);
578  result.added = true;
579  result.user_data = info->user_data;
580  info->add_view_callback(&result);
581 
582  return kSuccess;
583  }));
584 
585  FlutterViewId view_id =
586  fl_engine_add_view(engine, 123, 456, 2.0, nullptr, add_view_cb, loop);
587  EXPECT_GT(view_id, 0);
588  EXPECT_TRUE(called);
589 
590  // Blocks here until add_view_cb is called.
591  g_main_loop_run(loop);
592 }

References add_view_cb(), fl_engine_add_view(), fl_engine_get_embedder_api(), make_mock_engine(), and result.

◆ TEST() [2/21]

TEST ( FlEngineTest  ,
AddViewEngineError   
)

Definition at line 641 of file fl_engine_test.cc.

641  {
642  g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
643 
644  g_autoptr(FlEngine) engine = make_mock_engine();
645  FlutterEngineProcTable* embedder_api = fl_engine_get_embedder_api(engine);
646 
647  embedder_api->AddView = MOCK_ENGINE_PROC(
648  AddView, ([](auto engine, const FlutterAddViewInfo* info) {
649  return kInvalidArguments;
650  }));
651 
652  FlutterViewId view_id = fl_engine_add_view(engine, 123, 456, 2.0, nullptr,
654  EXPECT_GT(view_id, 0);
655 
656  // Blocks here until remove_view_engine_error_cb is called.
657  g_main_loop_run(loop);
658 }

References add_view_engine_error_cb(), fl_engine_add_view(), fl_engine_get_embedder_api(), and make_mock_engine().

◆ TEST() [3/21]

TEST ( FlEngineTest  ,
AddViewError   
)

Definition at line 605 of file fl_engine_test.cc.

605  {
606  g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
607 
608  g_autoptr(FlEngine) engine = make_mock_engine();
609  FlutterEngineProcTable* embedder_api = fl_engine_get_embedder_api(engine);
610 
611  embedder_api->AddView = MOCK_ENGINE_PROC(
612  AddView, ([](auto engine, const FlutterAddViewInfo* info) {
613  FlutterAddViewResult result;
614  result.struct_size = sizeof(FlutterAddViewResult);
615  result.added = false;
616  result.user_data = info->user_data;
617  info->add_view_callback(&result);
618 
619  return kSuccess;
620  }));
621 
622  FlutterViewId view_id = fl_engine_add_view(engine, 123, 456, 2.0, nullptr,
623  add_view_error_cb, loop);
624  EXPECT_GT(view_id, 0);
625 
626  // Blocks here until add_view_error_cb is called.
627  g_main_loop_run(loop);
628 }

References add_view_error_cb(), fl_engine_add_view(), fl_engine_get_embedder_api(), make_mock_engine(), and result.

◆ TEST() [4/21]

TEST ( FlEngineTest  ,
CLocale   
)

Definition at line 409 of file fl_engine_test.cc.

409  {
410  g_autofree gchar* initial_language = g_strdup(g_getenv("LANGUAGE"));
411  g_setenv("LANGUAGE", "C", TRUE);
412  g_autoptr(FlDartProject) project = fl_dart_project_new();
413 
414  g_autoptr(FlEngine) engine = make_mock_engine_with_project(project);
415  FlutterEngineProcTable* embedder_api = fl_engine_get_embedder_api(engine);
416 
417  bool called = false;
418  embedder_api->UpdateLocales = MOCK_ENGINE_PROC(
419  UpdateLocales, ([&called](auto engine, const FlutterLocale** locales,
420  size_t locales_count) {
421  called = true;
422 
423  EXPECT_EQ(locales_count, static_cast<size_t>(1));
424 
425  EXPECT_STREQ(locales[0]->language_code, "C");
426  EXPECT_STREQ(locales[0]->country_code, nullptr);
427  EXPECT_STREQ(locales[0]->script_code, nullptr);
428  EXPECT_STREQ(locales[0]->variant_code, nullptr);
429 
430  return kSuccess;
431  }));
432 
433  g_autoptr(GError) error = nullptr;
434  EXPECT_TRUE(fl_engine_start(engine, &error));
435  EXPECT_EQ(error, nullptr);
436 
437  EXPECT_TRUE(called);
438 
439  if (initial_language) {
440  g_setenv("LANGUAGE", initial_language, TRUE);
441  } else {
442  g_unsetenv("LANGUAGE");
443  }
444 }

References error, fl_dart_project_new(), fl_engine_get_embedder_api(), fl_engine_start(), and TRUE.

◆ TEST() [5/21]

TEST ( FlEngineTest  ,
DartEntrypointArgs   
)

Definition at line 322 of file fl_engine_test.cc.

322  {
323  g_autoptr(FlDartProject) project = fl_dart_project_new();
324 
325  GPtrArray* args_array = g_ptr_array_new();
326  g_ptr_array_add(args_array, const_cast<char*>("arg_one"));
327  g_ptr_array_add(args_array, const_cast<char*>("arg_two"));
328  g_ptr_array_add(args_array, const_cast<char*>("arg_three"));
329  g_ptr_array_add(args_array, nullptr);
330  gchar** args = reinterpret_cast<gchar**>(g_ptr_array_free(args_array, false));
331 
333 
334  g_autoptr(FlEngine) engine = make_mock_engine_with_project(project);
335  FlutterEngineProcTable* embedder_api = fl_engine_get_embedder_api(engine);
336 
337  bool called = false;
338  embedder_api->Initialize = MOCK_ENGINE_PROC(
339  Initialize, ([&called, &set_args = args](
340  size_t version, const FlutterRendererConfig* config,
341  const FlutterProjectArgs* args, void* user_data,
342  FLUTTER_API_SYMBOL(FlutterEngine) * engine_out) {
343  called = true;
344  EXPECT_NE(set_args, args->dart_entrypoint_argv);
345  EXPECT_EQ(args->dart_entrypoint_argc, 3);
346 
347  return kSuccess;
348  }));
349 
350  g_autoptr(GError) error = nullptr;
351  EXPECT_TRUE(fl_engine_start(engine, &error));
352  EXPECT_EQ(error, nullptr);
353 
354  EXPECT_TRUE(called);
355 }

References args, error, fl_dart_project_new(), fl_dart_project_set_dart_entrypoint_arguments(), fl_engine_get_embedder_api(), fl_engine_start(), and user_data.

◆ TEST() [6/21]

TEST ( FlEngineTest  ,
DispatchSemanticsAction   
)

Definition at line 120 of file fl_engine_test.cc.

120  {
121  g_autoptr(FlEngine) engine = make_mock_engine();
122  FlutterEngineProcTable* embedder_api = fl_engine_get_embedder_api(engine);
123 
124  bool called = false;
125  embedder_api->DispatchSemanticsAction = MOCK_ENGINE_PROC(
126  DispatchSemanticsAction,
127  ([&called](auto engine, uint64_t id, FlutterSemanticsAction action,
128  const uint8_t* data, size_t data_length) {
129  EXPECT_EQ(id, static_cast<uint64_t>(42));
130  EXPECT_EQ(action, kFlutterSemanticsActionTap);
131  EXPECT_EQ(data_length, static_cast<size_t>(4));
132  EXPECT_EQ(data[0], 't');
133  EXPECT_EQ(data[1], 'e');
134  EXPECT_EQ(data[2], 's');
135  EXPECT_EQ(data[3], 't');
136  called = true;
137 
138  return kSuccess;
139  }));
140 
141  g_autoptr(GError) error = nullptr;
142  EXPECT_TRUE(fl_engine_start(engine, &error));
143  EXPECT_EQ(error, nullptr);
144  g_autoptr(GBytes) data = g_bytes_new_static("test", 4);
145  fl_engine_dispatch_semantics_action(engine, 42, kFlutterSemanticsActionTap,
146  data);
147 
148  EXPECT_TRUE(called);
149 }

References error, fl_engine_dispatch_semantics_action(), fl_engine_get_embedder_api(), fl_engine_start(), and make_mock_engine().

◆ TEST() [7/21]

TEST ( FlEngineTest  ,
DuplicateLocale   
)

Definition at line 446 of file fl_engine_test.cc.

446  {
447  g_autofree gchar* initial_language = g_strdup(g_getenv("LANGUAGE"));
448  g_setenv("LANGUAGE", "en:en", TRUE);
449  g_autoptr(FlDartProject) project = fl_dart_project_new();
450 
451  g_autoptr(FlEngine) engine = make_mock_engine_with_project(project);
452  FlutterEngineProcTable* embedder_api = fl_engine_get_embedder_api(engine);
453 
454  bool called = false;
455  embedder_api->UpdateLocales = MOCK_ENGINE_PROC(
456  UpdateLocales, ([&called](auto engine, const FlutterLocale** locales,
457  size_t locales_count) {
458  called = true;
459 
460  EXPECT_EQ(locales_count, static_cast<size_t>(2));
461 
462  EXPECT_STREQ(locales[0]->language_code, "en");
463  EXPECT_STREQ(locales[0]->country_code, nullptr);
464  EXPECT_STREQ(locales[0]->script_code, nullptr);
465  EXPECT_STREQ(locales[0]->variant_code, nullptr);
466 
467  EXPECT_STREQ(locales[1]->language_code, "C");
468  EXPECT_STREQ(locales[1]->country_code, nullptr);
469  EXPECT_STREQ(locales[1]->script_code, nullptr);
470  EXPECT_STREQ(locales[1]->variant_code, nullptr);
471 
472  return kSuccess;
473  }));
474 
475  g_autoptr(GError) error = nullptr;
476  EXPECT_TRUE(fl_engine_start(engine, &error));
477  EXPECT_EQ(error, nullptr);
478 
479  EXPECT_TRUE(called);
480 
481  if (initial_language) {
482  g_setenv("LANGUAGE", initial_language, TRUE);
483  } else {
484  g_unsetenv("LANGUAGE");
485  }
486 }

References error, fl_dart_project_new(), fl_engine_get_embedder_api(), fl_engine_start(), and TRUE.

◆ TEST() [8/21]

TEST ( FlEngineTest  ,
EmptyLocales   
)

Definition at line 488 of file fl_engine_test.cc.

488  {
489  g_autofree gchar* initial_language = g_strdup(g_getenv("LANGUAGE"));
490  g_setenv("LANGUAGE", "de:: :en_US", TRUE);
491  g_autoptr(FlDartProject) project = fl_dart_project_new();
492 
493  g_autoptr(FlEngine) engine = make_mock_engine_with_project(project);
494  FlutterEngineProcTable* embedder_api = fl_engine_get_embedder_api(engine);
495 
496  bool called = false;
497  embedder_api->UpdateLocales = MOCK_ENGINE_PROC(
498  UpdateLocales, ([&called](auto engine, const FlutterLocale** locales,
499  size_t locales_count) {
500  called = true;
501 
502  EXPECT_EQ(locales_count, static_cast<size_t>(4));
503 
504  EXPECT_STREQ(locales[0]->language_code, "de");
505  EXPECT_STREQ(locales[0]->country_code, nullptr);
506  EXPECT_STREQ(locales[0]->script_code, nullptr);
507  EXPECT_STREQ(locales[0]->variant_code, nullptr);
508 
509  EXPECT_STREQ(locales[1]->language_code, "en");
510  EXPECT_STREQ(locales[1]->country_code, "US");
511  EXPECT_STREQ(locales[1]->script_code, nullptr);
512  EXPECT_STREQ(locales[1]->variant_code, nullptr);
513 
514  EXPECT_STREQ(locales[2]->language_code, "en");
515  EXPECT_STREQ(locales[2]->country_code, nullptr);
516  EXPECT_STREQ(locales[2]->script_code, nullptr);
517  EXPECT_STREQ(locales[2]->variant_code, nullptr);
518 
519  EXPECT_STREQ(locales[3]->language_code, "C");
520  EXPECT_STREQ(locales[3]->country_code, nullptr);
521  EXPECT_STREQ(locales[3]->script_code, nullptr);
522  EXPECT_STREQ(locales[3]->variant_code, nullptr);
523 
524  return kSuccess;
525  }));
526 
527  g_autoptr(GError) error = nullptr;
528  EXPECT_TRUE(fl_engine_start(engine, &error));
529  EXPECT_EQ(error, nullptr);
530 
531  EXPECT_TRUE(called);
532 
533  if (initial_language) {
534  g_setenv("LANGUAGE", initial_language, TRUE);
535  } else {
536  g_unsetenv("LANGUAGE");
537  }
538 }

References error, fl_dart_project_new(), fl_engine_get_embedder_api(), fl_engine_start(), and TRUE.

◆ TEST() [9/21]

TEST ( FlEngineTest  ,
Locales   
)

Definition at line 357 of file fl_engine_test.cc.

357  {
358  g_autofree gchar* initial_language = g_strdup(g_getenv("LANGUAGE"));
359  g_setenv("LANGUAGE", "de:en_US", TRUE);
360  g_autoptr(FlDartProject) project = fl_dart_project_new();
361 
362  g_autoptr(FlEngine) engine = make_mock_engine_with_project(project);
363  FlutterEngineProcTable* embedder_api = fl_engine_get_embedder_api(engine);
364 
365  bool called = false;
366  embedder_api->UpdateLocales = MOCK_ENGINE_PROC(
367  UpdateLocales, ([&called](auto engine, const FlutterLocale** locales,
368  size_t locales_count) {
369  called = true;
370 
371  EXPECT_EQ(locales_count, static_cast<size_t>(4));
372 
373  EXPECT_STREQ(locales[0]->language_code, "de");
374  EXPECT_STREQ(locales[0]->country_code, nullptr);
375  EXPECT_STREQ(locales[0]->script_code, nullptr);
376  EXPECT_STREQ(locales[0]->variant_code, nullptr);
377 
378  EXPECT_STREQ(locales[1]->language_code, "en");
379  EXPECT_STREQ(locales[1]->country_code, "US");
380  EXPECT_STREQ(locales[1]->script_code, nullptr);
381  EXPECT_STREQ(locales[1]->variant_code, nullptr);
382 
383  EXPECT_STREQ(locales[2]->language_code, "en");
384  EXPECT_STREQ(locales[2]->country_code, nullptr);
385  EXPECT_STREQ(locales[2]->script_code, nullptr);
386  EXPECT_STREQ(locales[2]->variant_code, nullptr);
387 
388  EXPECT_STREQ(locales[3]->language_code, "C");
389  EXPECT_STREQ(locales[3]->country_code, nullptr);
390  EXPECT_STREQ(locales[3]->script_code, nullptr);
391  EXPECT_STREQ(locales[3]->variant_code, nullptr);
392 
393  return kSuccess;
394  }));
395 
396  g_autoptr(GError) error = nullptr;
397  EXPECT_TRUE(fl_engine_start(engine, &error));
398  EXPECT_EQ(error, nullptr);
399 
400  EXPECT_TRUE(called);
401 
402  if (initial_language) {
403  g_setenv("LANGUAGE", initial_language, TRUE);
404  } else {
405  g_unsetenv("LANGUAGE");
406  }
407 }

References error, fl_dart_project_new(), fl_engine_get_embedder_api(), fl_engine_start(), and TRUE.

◆ TEST() [10/21]

TEST ( FlEngineTest  ,
MousePointer   
)

Definition at line 45 of file fl_engine_test.cc.

45  {
46  g_autoptr(FlEngine) engine = make_mock_engine();
47  FlutterEngineProcTable* embedder_api = fl_engine_get_embedder_api(engine);
48 
49  bool called = false;
50  embedder_api->SendPointerEvent = MOCK_ENGINE_PROC(
51  SendPointerEvent,
52  ([&called](auto engine, const FlutterPointerEvent* events,
53  size_t events_count) {
54  called = true;
55  EXPECT_EQ(events_count, static_cast<size_t>(1));
56  EXPECT_EQ(events[0].view_id, 1);
57  EXPECT_EQ(events[0].phase, kDown);
58  EXPECT_EQ(events[0].timestamp, static_cast<size_t>(1234567890));
59  EXPECT_EQ(events[0].x, 800);
60  EXPECT_EQ(events[0].y, 600);
61  EXPECT_EQ(events[0].device, static_cast<int32_t>(0));
62  EXPECT_EQ(events[0].signal_kind, kFlutterPointerSignalKindScroll);
63  EXPECT_EQ(events[0].scroll_delta_x, 1.2);
64  EXPECT_EQ(events[0].scroll_delta_y, -3.4);
65  EXPECT_EQ(events[0].device_kind, kFlutterPointerDeviceKindMouse);
66  EXPECT_EQ(events[0].buttons, kFlutterPointerButtonMouseSecondary);
67 
68  return kSuccess;
69  }));
70 
71  g_autoptr(GError) error = nullptr;
72  EXPECT_TRUE(fl_engine_start(engine, &error));
73  EXPECT_EQ(error, nullptr);
74  fl_engine_send_mouse_pointer_event(engine, 1, kDown, 1234567890, 800, 600,
75  kFlutterPointerDeviceKindMouse, 1.2, -3.4,
76  kFlutterPointerButtonMouseSecondary);
77 
78  EXPECT_TRUE(called);
79 }

References error, fl_engine_get_embedder_api(), fl_engine_send_mouse_pointer_event(), fl_engine_start(), and make_mock_engine().

◆ TEST() [11/21]

TEST ( FlEngineTest  ,
OnPreEngineRestart   
)

Definition at line 279 of file fl_engine_test.cc.

279  {
280  g_autoptr(FlEngine) engine = make_mock_engine();
281  FlutterEngineProcTable* embedder_api = fl_engine_get_embedder_api(engine);
282 
283  OnPreEngineRestartCallback callback;
284  void* callback_user_data;
285 
286  bool called = false;
287  embedder_api->Initialize = MOCK_ENGINE_PROC(
288  Initialize, ([&callback, &callback_user_data, &called](
289  size_t version, const FlutterRendererConfig* config,
290  const FlutterProjectArgs* args, void* user_data,
291  FLUTTER_API_SYMBOL(FlutterEngine) * engine_out) {
292  called = true;
293  callback = args->on_pre_engine_restart_callback;
294  callback_user_data = user_data;
295 
296  return kSuccess;
297  }));
298 
299  g_autoptr(GError) error = nullptr;
300  EXPECT_TRUE(fl_engine_start(engine, &error));
301  EXPECT_EQ(error, nullptr);
302 
303  EXPECT_TRUE(called);
304  EXPECT_NE(callback, nullptr);
305 
306  // The following call has no effect but should not crash.
307  callback(callback_user_data);
308 
309  int count = 0;
310 
311  // Set handler so that:
312  //
313  // * When the engine restarts, count += 1;
314  // * When the engine is freed, count += 10.
315  g_signal_connect(engine, "on-pre-engine-restart",
316  G_CALLBACK(on_pre_engine_restart_cb), &count);
317 
318  callback(callback_user_data);
319  EXPECT_EQ(count, 1);
320 }

References args, callback, error, fl_engine_get_embedder_api(), fl_engine_start(), make_mock_engine(), on_pre_engine_restart_cb(), and user_data.

◆ TEST() [12/21]

TEST ( FlEngineTest  ,
PlatformMessage   
)

Definition at line 152 of file fl_engine_test.cc.

152  {
153  g_autoptr(FlEngine) engine = make_mock_engine();
154  FlutterEngineProcTable* embedder_api = fl_engine_get_embedder_api(engine);
155 
156  bool called = false;
157  FlutterEngineSendPlatformMessageFnPtr old_handler =
158  embedder_api->SendPlatformMessage;
159  embedder_api->SendPlatformMessage = MOCK_ENGINE_PROC(
160  SendPlatformMessage,
161  ([&called, old_handler](auto engine,
162  const FlutterPlatformMessage* message) {
163  if (strcmp(message->channel, "test") != 0) {
164  return old_handler(engine, message);
165  }
166 
167  called = true;
168 
169  EXPECT_EQ(message->message_size, static_cast<size_t>(4));
170  EXPECT_EQ(message->message[0], 't');
171  EXPECT_EQ(message->message[1], 'e');
172  EXPECT_EQ(message->message[2], 's');
173  EXPECT_EQ(message->message[3], 't');
174 
175  return kSuccess;
176  }));
177 
178  g_autoptr(GError) error = nullptr;
179  EXPECT_TRUE(fl_engine_start(engine, &error));
180  EXPECT_EQ(error, nullptr);
181  g_autoptr(GBytes) message = g_bytes_new_static("test", 4);
182  fl_engine_send_platform_message(engine, "test", message, nullptr, nullptr,
183  nullptr);
184 
185  EXPECT_TRUE(called);
186 }

References error, fl_engine_get_embedder_api(), fl_engine_send_platform_message(), fl_engine_start(), and make_mock_engine().

◆ TEST() [13/21]

TEST ( FlEngineTest  ,
PlatformMessageResponse   
)

Definition at line 189 of file fl_engine_test.cc.

189  {
190  g_autoptr(FlEngine) engine = make_mock_engine();
191  FlutterEngineProcTable* embedder_api = fl_engine_get_embedder_api(engine);
192 
193  bool called = false;
194  embedder_api->SendPlatformMessageResponse = MOCK_ENGINE_PROC(
195  SendPlatformMessageResponse,
196  ([&called](auto engine,
197  const FlutterPlatformMessageResponseHandle* handle,
198  const uint8_t* data, size_t data_length) {
199  called = true;
200 
201  EXPECT_EQ(
202  handle,
203  reinterpret_cast<const FlutterPlatformMessageResponseHandle*>(42));
204  EXPECT_EQ(data_length, static_cast<size_t>(4));
205  EXPECT_EQ(data[0], 't');
206  EXPECT_EQ(data[1], 'e');
207  EXPECT_EQ(data[2], 's');
208  EXPECT_EQ(data[3], 't');
209 
210  return kSuccess;
211  }));
212 
213  g_autoptr(GError) error = nullptr;
214  EXPECT_TRUE(fl_engine_start(engine, &error));
215  EXPECT_EQ(error, nullptr);
216  g_autoptr(GBytes) response = g_bytes_new_static("test", 4);
218  engine, reinterpret_cast<const FlutterPlatformMessageResponseHandle*>(42),
219  response, &error));
220  EXPECT_EQ(error, nullptr);
221 
222  EXPECT_TRUE(called);
223 }

References error, fl_engine_get_embedder_api(), fl_engine_send_platform_message_response(), fl_engine_start(), and make_mock_engine().

◆ TEST() [14/21]

TEST ( FlEngineTest  ,
PointerPanZoom   
)

Definition at line 82 of file fl_engine_test.cc.

82  {
83  g_autoptr(FlEngine) engine = make_mock_engine();
84  FlutterEngineProcTable* embedder_api = fl_engine_get_embedder_api(engine);
85 
86  bool called = false;
87  embedder_api->SendPointerEvent = MOCK_ENGINE_PROC(
88  SendPointerEvent,
89  ([&called](auto engine, const FlutterPointerEvent* events,
90  size_t events_count) {
91  called = true;
92  EXPECT_EQ(events_count, static_cast<size_t>(1));
93  EXPECT_EQ(events[0].view_id, 1);
94  EXPECT_EQ(events[0].phase, kPanZoomUpdate);
95  EXPECT_EQ(events[0].timestamp, static_cast<size_t>(1234567890));
96  EXPECT_EQ(events[0].x, 800);
97  EXPECT_EQ(events[0].y, 600);
98  EXPECT_EQ(events[0].device, static_cast<int32_t>(1));
99  EXPECT_EQ(events[0].signal_kind, kFlutterPointerSignalKindNone);
100  EXPECT_EQ(events[0].pan_x, 1.5);
101  EXPECT_EQ(events[0].pan_y, 2.5);
102  EXPECT_EQ(events[0].scale, 3.5);
103  EXPECT_EQ(events[0].rotation, 4.5);
104  EXPECT_EQ(events[0].device_kind, kFlutterPointerDeviceKindTrackpad);
105  EXPECT_EQ(events[0].buttons, 0);
106 
107  return kSuccess;
108  }));
109 
110  g_autoptr(GError) error = nullptr;
111  EXPECT_TRUE(fl_engine_start(engine, &error));
112  EXPECT_EQ(error, nullptr);
113  fl_engine_send_pointer_pan_zoom_event(engine, 1, 1234567890, 800, 600,
114  kPanZoomUpdate, 1.5, 2.5, 3.5, 4.5);
115 
116  EXPECT_TRUE(called);
117 }

References error, fl_engine_get_embedder_api(), fl_engine_send_pointer_pan_zoom_event(), fl_engine_start(), and make_mock_engine().

◆ TEST() [15/21]

TEST ( FlEngineTest  ,
RemoveView   
)

Definition at line 671 of file fl_engine_test.cc.

671  {
672  g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
673 
674  g_autoptr(FlEngine) engine = make_mock_engine();
675  FlutterEngineProcTable* embedder_api = fl_engine_get_embedder_api(engine);
676 
677  bool called = false;
678  embedder_api->RemoveView = MOCK_ENGINE_PROC(
679  RemoveView, ([&called](auto engine, const FlutterRemoveViewInfo* info) {
680  called = true;
681  EXPECT_EQ(info->view_id, 123);
682 
683  FlutterRemoveViewResult result;
684  result.struct_size = sizeof(FlutterRemoveViewResult);
685  result.removed = true;
686  result.user_data = info->user_data;
687  info->remove_view_callback(&result);
688 
689  return kSuccess;
690  }));
691 
692  fl_engine_remove_view(engine, 123, nullptr, remove_view_cb, loop);
693  EXPECT_TRUE(called);
694 
695  // Blocks here until remove_view_cb is called.
696  g_main_loop_run(loop);
697 }

References fl_engine_get_embedder_api(), fl_engine_remove_view(), make_mock_engine(), remove_view_cb(), and result.

◆ TEST() [16/21]

TEST ( FlEngineTest  ,
RemoveViewEngineError   
)

Definition at line 744 of file fl_engine_test.cc.

744  {
745  g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
746 
747  g_autoptr(FlEngine) engine = make_mock_engine();
748  FlutterEngineProcTable* embedder_api = fl_engine_get_embedder_api(engine);
749 
750  embedder_api->RemoveView = MOCK_ENGINE_PROC(
751  RemoveView, ([](auto engine, const FlutterRemoveViewInfo* info) {
752  return kInvalidArguments;
753  }));
754 
756  loop);
757 
758  // Blocks here until remove_view_engine_error_cb is called.
759  g_main_loop_run(loop);
760 }

References fl_engine_get_embedder_api(), fl_engine_remove_view(), make_mock_engine(), and remove_view_engine_error_cb().

◆ TEST() [17/21]

TEST ( FlEngineTest  ,
RemoveViewError   
)

Definition at line 710 of file fl_engine_test.cc.

710  {
711  g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
712 
713  g_autoptr(FlEngine) engine = make_mock_engine();
714  FlutterEngineProcTable* embedder_api = fl_engine_get_embedder_api(engine);
715 
716  embedder_api->RemoveView = MOCK_ENGINE_PROC(
717  RemoveView, ([](auto engine, const FlutterRemoveViewInfo* info) {
718  FlutterRemoveViewResult result;
719  result.struct_size = sizeof(FlutterRemoveViewResult);
720  result.removed = false;
721  result.user_data = info->user_data;
722  info->remove_view_callback(&result);
723 
724  return kSuccess;
725  }));
726 
727  fl_engine_remove_view(engine, 123, nullptr, remove_view_error_cb, loop);
728 
729  // Blocks here until remove_view_error_cb is called.
730  g_main_loop_run(loop);
731 }

References fl_engine_get_embedder_api(), fl_engine_remove_view(), make_mock_engine(), remove_view_error_cb(), and result.

◆ TEST() [18/21]

TEST ( FlEngineTest  ,
SettingsHandler   
)

Definition at line 226 of file fl_engine_test.cc.

226  {
227  g_autoptr(FlEngine) engine = make_mock_engine();
228  FlutterEngineProcTable* embedder_api = fl_engine_get_embedder_api(engine);
229 
230  bool called = false;
231  embedder_api->SendPlatformMessage = MOCK_ENGINE_PROC(
232  SendPlatformMessage,
233  ([&called](auto engine, const FlutterPlatformMessage* message) {
234  called = true;
235 
236  EXPECT_STREQ(message->channel, "flutter/settings");
237 
238  g_autoptr(FlJsonMessageCodec) codec = fl_json_message_codec_new();
239  g_autoptr(GBytes) data =
240  g_bytes_new(message->message, message->message_size);
241  g_autoptr(GError) error = nullptr;
242  g_autoptr(FlValue) settings = fl_message_codec_decode_message(
243  FL_MESSAGE_CODEC(codec), data, &error);
244  EXPECT_NE(settings, nullptr);
245  EXPECT_EQ(error, nullptr);
246 
247  FlValue* text_scale_factor =
248  fl_value_lookup_string(settings, "textScaleFactor");
249  EXPECT_NE(text_scale_factor, nullptr);
250  EXPECT_EQ(fl_value_get_type(text_scale_factor), FL_VALUE_TYPE_FLOAT);
251 
252  FlValue* always_use_24hr_format =
253  fl_value_lookup_string(settings, "alwaysUse24HourFormat");
254  EXPECT_NE(always_use_24hr_format, nullptr);
255  EXPECT_EQ(fl_value_get_type(always_use_24hr_format),
257 
258  FlValue* platform_brightness =
259  fl_value_lookup_string(settings, "platformBrightness");
260  EXPECT_NE(platform_brightness, nullptr);
261  EXPECT_EQ(fl_value_get_type(platform_brightness), FL_VALUE_TYPE_STRING);
262 
263  return kSuccess;
264  }));
265 
266  g_autoptr(GError) error = nullptr;
267  EXPECT_TRUE(fl_engine_start(engine, &error));
268  EXPECT_EQ(error, nullptr);
269 
270  EXPECT_TRUE(called);
271 }

References error, fl_engine_get_embedder_api(), fl_engine_start(), fl_json_message_codec_new(), fl_message_codec_decode_message(), fl_value_get_type(), fl_value_lookup_string(), FL_VALUE_TYPE_BOOL, FL_VALUE_TYPE_FLOAT, FL_VALUE_TYPE_STRING, and make_mock_engine().

◆ TEST() [19/21]

TEST ( FlEngineTest  ,
Switches   
)

Definition at line 763 of file fl_engine_test.cc.

763  {
764  g_autoptr(FlEngine) engine = make_mock_engine();
765 
766  setenv("FLUTTER_ENGINE_SWITCHES", "2", 1);
767  setenv("FLUTTER_ENGINE_SWITCH_1", "abc", 1);
768  setenv("FLUTTER_ENGINE_SWITCH_2", "foo=\"bar, baz\"", 1);
769 
770  g_autoptr(GPtrArray) switches = fl_engine_get_switches(engine);
771  EXPECT_EQ(switches->len, 2U);
772  EXPECT_STREQ(static_cast<const char*>(g_ptr_array_index(switches, 0)),
773  "--abc");
774  EXPECT_STREQ(static_cast<const char*>(g_ptr_array_index(switches, 1)),
775  "--foo=\"bar, baz\"");
776 
777  unsetenv("FLUTTER_ENGINE_SWITCHES");
778  unsetenv("FLUTTER_ENGINE_SWITCH_1");
779  unsetenv("FLUTTER_ENGINE_SWITCH_2");
780 }

References fl_engine_get_switches(), and make_mock_engine().

◆ TEST() [20/21]

TEST ( FlEngineTest  ,
SwitchesEmpty   
)

Definition at line 540 of file fl_engine_test.cc.

540  {
541  g_autoptr(FlEngine) engine = make_mock_engine();
542 
543  // Clear the main environment variable, since test order is not guaranteed.
544  unsetenv("FLUTTER_ENGINE_SWITCHES");
545 
546  g_autoptr(GPtrArray) switches = fl_engine_get_switches(engine);
547 
548  EXPECT_EQ(switches->len, 0U);
549 }

References fl_engine_get_switches(), and make_mock_engine().

◆ TEST() [21/21]

TEST ( FlEngineTest  ,
WindowMetrics   
)

Definition at line 19 of file fl_engine_test.cc.

19  {
20  g_autoptr(FlEngine) engine = make_mock_engine();
21  FlutterEngineProcTable* embedder_api = fl_engine_get_embedder_api(engine);
22 
23  bool called = false;
24  embedder_api->SendWindowMetricsEvent = MOCK_ENGINE_PROC(
25  SendWindowMetricsEvent,
26  ([&called](auto engine, const FlutterWindowMetricsEvent* event) {
27  called = true;
28  EXPECT_EQ(event->view_id, 1);
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);
32 
33  return kSuccess;
34  }));
35 
36  g_autoptr(GError) error = nullptr;
37  EXPECT_TRUE(fl_engine_start(engine, &error));
38  EXPECT_EQ(error, nullptr);
39  fl_engine_send_window_metrics_event(engine, 1, 3840, 2160, 2.0);
40 
41  EXPECT_TRUE(called);
42 }

References error, event, fl_engine_get_embedder_api(), fl_engine_send_window_metrics_event(), fl_engine_start(), and make_mock_engine().

event
FlKeyEvent * event
Definition: fl_key_channel_responder.cc:118
fl_engine_get_embedder_api
FlutterEngineProcTable * fl_engine_get_embedder_api(FlEngine *self)
Definition: fl_engine.cc:637
add_view_engine_error_cb
static void add_view_engine_error_cb(GObject *object, GAsyncResult *result, gpointer user_data)
Definition: fl_engine_test.cc:630
FlValue
typedefG_BEGIN_DECLS struct _FlValue FlValue
Definition: fl_value.h:42
fl_json_message_codec_new
G_MODULE_EXPORT FlJsonMessageCodec * fl_json_message_codec_new()
Definition: fl_json_message_codec.cc:306
fl_engine_remove_view
void fl_engine_remove_view(FlEngine *self, FlutterViewId view_id, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
Definition: fl_engine.cc:686
user_data
FlKeyEvent uint64_t FlKeyResponderAsyncCallback gpointer user_data
Definition: fl_key_channel_responder.cc:121
fl_engine_dispatch_semantics_action
void fl_engine_dispatch_semantics_action(FlEngine *self, uint64_t id, FlutterSemanticsAction action, GBytes *data)
Definition: fl_engine.cc:953
fl_dart_project_new
G_MODULE_EXPORT FlDartProject * fl_dart_project_new()
Definition: fl_dart_project.cc:50
fl_value_lookup_string
G_MODULE_EXPORT FlValue * fl_value_lookup_string(FlValue *self, const gchar *key)
Definition: fl_value.cc:811
fl_engine_send_window_metrics_event
void fl_engine_send_window_metrics_event(FlEngine *self, FlutterViewId view_id, size_t width, size_t height, double pixel_ratio)
Definition: fl_engine.cc:854
make_mock_engine
static FlEngine * make_mock_engine()
Definition: fl_event_channel_test.cc:24
fl_message_codec_decode_message
G_MODULE_EXPORT FlValue * fl_message_codec_decode_message(FlMessageCodec *self, GBytes *message, GError **error)
Definition: fl_message_codec.cc:33
fl_value_get_type
G_MODULE_EXPORT FlValueType fl_value_get_type(FlValue *self)
Definition: fl_value.cc:466
fl_engine_add_view_finish
gboolean fl_engine_add_view_finish(FlEngine *self, GAsyncResult *result, GError **error)
Definition: fl_engine.cc:679
fl_engine_remove_view_finish
gboolean fl_engine_remove_view_finish(FlEngine *self, GAsyncResult *result, GError **error)
Definition: fl_engine.cc:711
FL_VALUE_TYPE_STRING
@ FL_VALUE_TYPE_STRING
Definition: fl_value.h:69
fl_dart_project_set_dart_entrypoint_arguments
G_MODULE_EXPORT void fl_dart_project_set_dart_entrypoint_arguments(FlDartProject *self, char **argv)
Definition: fl_dart_project.cc:110
remove_view_engine_error_cb
static void remove_view_engine_error_cb(GObject *object, GAsyncResult *result, gpointer user_data)
Definition: fl_engine_test.cc:733
TRUE
return TRUE
Definition: fl_pixel_buffer_texture_test.cc:53
fl_engine_add_view
FlutterViewId fl_engine_add_view(FlEngine *self, size_t width, size_t height, double pixel_ratio, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
Definition: fl_engine.cc:641
add_view_error_cb
static void add_view_error_cb(GObject *object, GAsyncResult *result, gpointer user_data)
Definition: fl_engine_test.cc:594
add_view_cb
static void add_view_cb(GObject *object, GAsyncResult *result, gpointer user_data)
Definition: fl_engine_test.cc:551
remove_view_cb
static void remove_view_cb(GObject *object, GAsyncResult *result, gpointer user_data)
Definition: fl_engine_test.cc:660
result
GAsyncResult * result
Definition: fl_text_input_handler.cc:106
args
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
Definition: fl_event_channel.h:89
error
const uint8_t uint32_t uint32_t GError ** error
Definition: fl_pixel_buffer_texture_test.cc:40
fl_engine_send_pointer_pan_zoom_event
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)
Definition: fl_engine.cc:908
fl_engine_send_platform_message
void fl_engine_send_platform_message(FlEngine *self, const gchar *channel, GBytes *message, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
Definition: fl_engine.cc:786
on_pre_engine_restart_cb
void on_pre_engine_restart_cb(FlEngine *engine, gpointer user_data)
Definition: fl_engine_test.cc:273
fl_engine_start
gboolean fl_engine_start(FlEngine *self, GError **error)
Definition: fl_engine.cc:509
FL_VALUE_TYPE_FLOAT
@ FL_VALUE_TYPE_FLOAT
Definition: fl_value.h:68
callback
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
Definition: fl_key_channel_responder.cc:120
remove_view_error_cb
static void remove_view_error_cb(GObject *object, GAsyncResult *result, gpointer user_data)
Definition: fl_engine_test.cc:699
fl_engine_send_mouse_pointer_event
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)
Definition: fl_engine.cc:874
fl_engine_get_switches
GPtrArray * fl_engine_get_switches(FlEngine *self)
Definition: fl_engine.cc:1028
FL_VALUE_TYPE_BOOL
@ FL_VALUE_TYPE_BOOL
Definition: fl_value.h:66
fl_engine_send_platform_message_response
gboolean fl_engine_send_platform_message_response(FlEngine *self, const FlutterPlatformMessageResponseHandle *handle, GBytes *response, GError **error)
Definition: fl_engine.cc:754