Flutter Linux Embedder
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
fl_view_test.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
6 #include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h"
8 #include "flutter/shell/platform/linux/testing/fl_test.h"
9 #include "flutter/shell/platform/linux/testing/fl_test_gtk_logs.h"
10 
11 #include "gtest/gtest.h"
12 
13 static void first_frame_cb(FlView* view, gboolean* first_frame_emitted) {
14  *first_frame_emitted = TRUE;
15 }
16 
17 TEST(FlViewTest, GetEngine) {
18  flutter::testing::fl_ensure_gtk_init();
19  g_autoptr(FlDartProject) project = fl_dart_project_new();
20  FlView* view = fl_view_new(project);
21 
22  // Check the engine is immediately available (i.e. before the widget is
23  // realized).
24  FlEngine* engine = fl_view_get_engine(view);
25  EXPECT_NE(engine, nullptr);
26 }
27 
28 TEST(FlViewTest, StateUpdateDoesNotHappenInInit) {
29  flutter::testing::fl_ensure_gtk_init();
30  g_autoptr(FlDartProject) project = fl_dart_project_new();
31  FlView* view = fl_view_new(project);
32  // Check that creating a view doesn't try to query the window state in
33  // initialization, causing a critical log to be issued.
34  EXPECT_EQ(
35  flutter::testing::fl_get_received_gtk_log_levels() & G_LOG_LEVEL_CRITICAL,
36  (GLogLevelFlags)0x0);
37 
38  (void)view;
39 }
40 
41 TEST(FlViewTest, FirstFrameSignal) {
42  flutter::testing::fl_ensure_gtk_init();
43 
44  g_autoptr(FlDartProject) project = fl_dart_project_new();
45  FlView* view = fl_view_new(project);
46  gboolean first_frame_emitted = FALSE;
47  g_signal_connect(view, "first-frame", G_CALLBACK(first_frame_cb),
48  &first_frame_emitted);
49 
50  EXPECT_FALSE(first_frame_emitted);
51 
52  fl_renderable_redraw(FL_RENDERABLE(view));
53 
54  // Signal is emitted in idle, clear the main loop.
55  while (g_main_context_iteration(g_main_context_default(), FALSE)) {
56  // Repeat until nothing to iterate on.
57  }
58 
59  // Check view has detected frame.
60  EXPECT_TRUE(first_frame_emitted);
61 }
62 
63 // Check secondary view is registered with engine.
64 TEST(FlViewTest, SecondaryView) {
65  flutter::testing::fl_ensure_gtk_init();
66 
67  g_autoptr(FlDartProject) project = fl_dart_project_new();
68  FlView* implicit_view = fl_view_new(project);
69 
70  FlEngine* engine = fl_view_get_engine(implicit_view);
71 
72  FlutterViewId view_id = -1;
73  fl_engine_get_embedder_api(engine)->AddView = MOCK_ENGINE_PROC(
74  AddView, ([&view_id](auto engine, const FlutterAddViewInfo* info) {
75  view_id = info->view_id;
76  FlutterAddViewResult result = {
77  .struct_size = sizeof(FlutterAddViewResult),
78  .added = true,
79  .user_data = info->user_data};
80  info->add_view_callback(&result);
81  return kSuccess;
82  }));
83 
84  g_autoptr(GError) error = nullptr;
85  EXPECT_TRUE(fl_engine_start(engine, &error));
86 
87  FlView* secondary_view = fl_view_new_for_engine(engine);
88  EXPECT_EQ(view_id, fl_view_get_id(secondary_view));
89 }
90 
91 // Check secondary view that fails registration.
92 TEST(FlViewTest, SecondaryViewError) {
93  flutter::testing::fl_ensure_gtk_init();
94 
95  g_autoptr(FlDartProject) project = fl_dart_project_new();
96  FlView* implicit_view = fl_view_new(project);
97 
98  FlEngine* engine = fl_view_get_engine(implicit_view);
99 
100  FlutterViewId view_id = -1;
101  fl_engine_get_embedder_api(engine)->AddView = MOCK_ENGINE_PROC(
102  AddView, ([&view_id](auto engine, const FlutterAddViewInfo* info) {
103  view_id = info->view_id;
104  return kInvalidArguments;
105  }));
106 
107  g_autoptr(GError) error = nullptr;
108  EXPECT_TRUE(fl_engine_start(engine, &error));
109 
110  FlView* secondary_view = fl_view_new_for_engine(engine);
111  EXPECT_EQ(view_id, fl_view_get_id(secondary_view));
112 }
113 
114 // Check views are deregistered on destruction.
115 TEST(FlViewTest, ViewDestroy) {
116  flutter::testing::fl_ensure_gtk_init();
117 
118  g_autoptr(FlDartProject) project = fl_dart_project_new();
119  FlView* implicit_view = fl_view_new(project);
120 
121  FlEngine* engine = fl_view_get_engine(implicit_view);
122 
123  g_autoptr(GPtrArray) removed_views = g_ptr_array_new();
124  fl_engine_get_embedder_api(engine)->RemoveView = MOCK_ENGINE_PROC(
125  RemoveView,
126  ([removed_views](auto engine, const FlutterRemoveViewInfo* info) {
127  g_ptr_array_add(removed_views, GINT_TO_POINTER(info->view_id));
128  return kSuccess;
129  }));
130 
131  g_autoptr(GError) error = nullptr;
132  EXPECT_TRUE(fl_engine_start(engine, &error));
133 
134  FlView* secondary_view = fl_view_new_for_engine(engine);
135 
136  int64_t implicit_view_id = fl_view_get_id(implicit_view);
137  int64_t secondary_view_id = fl_view_get_id(secondary_view);
138 
139  gtk_widget_destroy(GTK_WIDGET(secondary_view));
140  gtk_widget_destroy(GTK_WIDGET(implicit_view));
141 
142  EXPECT_EQ(removed_views->len, 2u);
143  EXPECT_EQ(GPOINTER_TO_INT(g_ptr_array_index(removed_views, 0)),
144  secondary_view_id);
145  EXPECT_EQ(GPOINTER_TO_INT(g_ptr_array_index(removed_views, 1)),
146  implicit_view_id);
147 }
148 
149 // Check views deregistered with errors works.
150 TEST(FlViewTest, ViewDestroyError) {
151  flutter::testing::fl_ensure_gtk_init();
152 
153  g_autoptr(FlDartProject) project = fl_dart_project_new();
154  FlView* implicit_view = fl_view_new(project);
155 
156  FlEngine* engine = fl_view_get_engine(implicit_view);
157 
158  fl_engine_get_embedder_api(engine)->RemoveView = MOCK_ENGINE_PROC(
159  RemoveView, ([](auto engine, const FlutterRemoveViewInfo* info) {
160  return kInvalidArguments;
161  }));
162 
163  g_autoptr(GError) error = nullptr;
164  EXPECT_TRUE(fl_engine_start(engine, &error));
165 
166  FlView* secondary_view = fl_view_new_for_engine(engine);
167 
168  gtk_widget_destroy(GTK_WIDGET(secondary_view));
169  gtk_widget_destroy(GTK_WIDGET(implicit_view));
170 }
FlView * view
G_MODULE_EXPORT FlDartProject * fl_dart_project_new()
FlutterEngineProcTable * fl_engine_get_embedder_api(FlEngine *self)
Definition: fl_engine.cc:661
gboolean fl_engine_start(FlEngine *self, GError **error)
Definition: fl_engine.cc:544
G_BEGIN_DECLS G_MODULE_EXPORT FlValue gpointer user_data
const uint8_t uint32_t uint32_t GError ** error
void fl_renderable_redraw(FlRenderable *self)
G_MODULE_EXPORT FlView * fl_view_new(FlDartProject *project)
Definition: fl_view.cc:775
G_MODULE_EXPORT FlView * fl_view_new_for_engine(FlEngine *engine)
Definition: fl_view.cc:803
G_MODULE_EXPORT FlEngine * fl_view_get_engine(FlView *self)
Definition: fl_view.cc:827
G_MODULE_EXPORT int64_t fl_view_get_id(FlView *self)
Definition: fl_view.cc:833
static void first_frame_cb(FlView *view, gboolean *first_frame_emitted)
Definition: fl_view_test.cc:13
TEST(FlViewTest, GetEngine)
Definition: fl_view_test.cc:17