| Flutter Linux Embedder |

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
5 #include "flutter/shell/platform/linux/public/flutter_linux/fl_view.h"
6 #include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h"
7 #include "flutter/shell/platform/linux/fl_engine_private.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 }
fl_engine_get_embedder_api
FlutterEngineProcTable * fl_engine_get_embedder_api(FlEngine *self)
Definition: fl_engine.cc:661
fl_view_get_id
G_MODULE_EXPORT int64_t fl_view_get_id(FlView *self)
Definition: fl_view.cc:833
fl_view_new_for_engine
G_MODULE_EXPORT FlView * fl_view_new_for_engine(FlEngine *engine)
Definition: fl_view.cc:803
fl_dart_project_new
G_MODULE_EXPORT FlDartProject * fl_dart_project_new()
Definition: fl_dart_project.cc:50
fl_view_new
G_MODULE_EXPORT FlView * fl_view_new(FlDartProject *project)
Definition: fl_view.cc:775
user_data
G_BEGIN_DECLS G_MODULE_EXPORT FlValue gpointer user_data
Definition: fl_event_channel.h:90
fl_engine_private.h
TRUE
return TRUE
Definition: fl_pixel_buffer_texture_test.cc:53
fl_view_get_engine
G_MODULE_EXPORT FlEngine * fl_view_get_engine(FlView *self)
Definition: fl_view.cc:827
fl_view.h
view
FlView * view
Definition: fl_application.cc:35
error
const uint8_t uint32_t uint32_t GError ** error
Definition: fl_pixel_buffer_texture_test.cc:40
fl_renderable_redraw
void fl_renderable_redraw(FlRenderable *self)
Definition: fl_renderable.cc:11
fl_engine_start
gboolean fl_engine_start(FlEngine *self, GError **error)
Definition: fl_engine.cc:544
TEST
TEST(FlViewTest, GetEngine)
Definition: fl_view_test.cc:17
first_frame_cb
static void first_frame_cb(FlView *view, gboolean *first_frame_emitted)
Definition: fl_view_test.cc:13