Flutter Engine
 
Loading...
Searching...
No Matches
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
12
13#include "gtest/gtest.h"
14
15// FIXME(robert-ancell): Disabled, see below.
16#if 0
17static void first_frame_cb(FlView* view, gboolean* first_frame_emitted) {
18 *first_frame_emitted = TRUE;
19}
20#endif
21
22TEST(FlViewTest, GetEngine) {
24 g_autoptr(FlDartProject) project = fl_dart_project_new();
25 FlView* view = fl_view_new(project);
26
27 // Check the engine is immediately available (i.e. before the widget is
28 // realized).
29 FlEngine* engine = fl_view_get_engine(view);
30 EXPECT_NE(engine, nullptr);
31}
32
33TEST(FlViewTest, StateUpdateDoesNotHappenInInit) {
35 g_autoptr(FlDartProject) project = fl_dart_project_new();
36 FlView* view = fl_view_new(project);
37 // Check that creating a view doesn't try to query the window state in
38 // initialization, causing a critical log to be issued.
39 EXPECT_EQ(
41 (GLogLevelFlags)0x0);
42
43 (void)view;
44}
45
46// FIXME(robert-ancell): Disabling this test as it requires the FlView
47// to be realized to work after some refactoring. This is proving to be
48// very difficult to mock. Following PRs will change this code so enable the
49// test again after that.
50#if 0
51TEST(FlViewTest, FirstFrameSignal) {
53
54 g_autoptr(FlDartProject) project = fl_dart_project_new();
55 FlView* view = fl_view_new(project);
56 gboolean first_frame_emitted = FALSE;
57 g_signal_connect(view, "first-frame", G_CALLBACK(first_frame_cb),
58 &first_frame_emitted);
59
60 EXPECT_FALSE(first_frame_emitted);
61
62 fl_renderable_present_layers(FL_RENDERABLE(view), nullptr, 0);
63
64 // Signal is emitted in idle, clear the main loop.
65 while (g_main_context_iteration(g_main_context_default(), FALSE)) {
66 // Repeat until nothing to iterate on.
67 }
68
69 // Check view has detected frame.
70 EXPECT_TRUE(first_frame_emitted);
71}
72#endif
73
74// Check semantics update applied
75TEST(FlViewTest, SemanticsUpdate) {
77
78 g_autoptr(FlDartProject) project = fl_dart_project_new();
79 FlView* view = fl_view_new(project);
80
81 FlEngine* engine = fl_view_get_engine(view);
82 g_autoptr(GError) error = nullptr;
83 EXPECT_TRUE(fl_engine_start(engine, &error));
84
85 FlutterSemanticsFlags flags = {};
86 FlutterSemanticsNode2 root_node = {
87 .id = 0, .label = "root", .flags2 = &flags};
88 FlutterSemanticsNode2* nodes[1] = {&root_node};
90 .node_count = 1, .nodes = nodes, .view_id = 0};
91 g_signal_emit_by_name(engine, "update-semantics", &update);
92
93 FlViewAccessible* accessible = fl_view_get_accessible(view);
94 EXPECT_EQ(atk_object_get_n_accessible_children(ATK_OBJECT(accessible)), 1);
95 AtkObject* root_object =
96 atk_object_ref_accessible_child(ATK_OBJECT(accessible), 0);
97 EXPECT_STREQ(atk_object_get_name(root_object), "root");
98}
99
100// Check semantics update ignored for other view
101TEST(FlViewTest, SemanticsUpdateOtherView) {
103
104 g_autoptr(FlDartProject) project = fl_dart_project_new();
105 FlView* view = fl_view_new(project);
106
107 FlEngine* engine = fl_view_get_engine(view);
108 g_autoptr(GError) error = nullptr;
109 EXPECT_TRUE(fl_engine_start(engine, &error));
110
111 FlutterSemanticsFlags flags = {};
112 FlutterSemanticsNode2 root_node = {
113 .id = 0, .label = "root", .flags2 = &flags};
114 FlutterSemanticsNode2* nodes[1] = {&root_node};
115 FlutterSemanticsUpdate2 update = {
116 .node_count = 1, .nodes = nodes, .view_id = 99};
117 g_signal_emit_by_name(engine, "update-semantics", &update);
118
119 FlViewAccessible* accessible = fl_view_get_accessible(view);
120 EXPECT_EQ(atk_object_get_n_accessible_children(ATK_OBJECT(accessible)), 0);
121}
122
123// Check secondary view is registered with engine.
124TEST(FlViewTest, SecondaryView) {
126
127 g_autoptr(FlDartProject) project = fl_dart_project_new();
128 FlView* implicit_view = fl_view_new(project);
129
130 FlEngine* engine = fl_view_get_engine(implicit_view);
131
134 AddView, ([&view_id](auto engine, const FlutterAddViewInfo* info) {
135 view_id = info->view_id;
136 FlutterAddViewResult result = {
138 .added = true,
139 .user_data = info->user_data};
140 info->add_view_callback(&result);
141 return kSuccess;
142 }));
143
144 g_autoptr(GError) error = nullptr;
145 EXPECT_TRUE(fl_engine_start(engine, &error));
146
147 FlView* secondary_view = fl_view_new_for_engine(engine);
148 EXPECT_EQ(view_id, fl_view_get_id(secondary_view));
149}
150
151// Check secondary view that fails registration.
152TEST(FlViewTest, SecondaryViewError) {
154
155 g_autoptr(FlDartProject) project = fl_dart_project_new();
156 FlView* implicit_view = fl_view_new(project);
157
158 FlEngine* engine = fl_view_get_engine(implicit_view);
159
162 AddView, ([&view_id](auto engine, const FlutterAddViewInfo* info) {
163 view_id = info->view_id;
164 return kInvalidArguments;
165 }));
166
167 g_autoptr(GError) error = nullptr;
168 EXPECT_TRUE(fl_engine_start(engine, &error));
169
170 FlView* secondary_view = fl_view_new_for_engine(engine);
171 EXPECT_EQ(view_id, fl_view_get_id(secondary_view));
172}
173
174// Check views are deregistered on destruction.
175TEST(FlViewTest, ViewDestroy) {
177
178 g_autoptr(FlDartProject) project = fl_dart_project_new();
179 FlView* implicit_view = fl_view_new(project);
180
181 FlEngine* engine = fl_view_get_engine(implicit_view);
182
183 g_autoptr(GPtrArray) removed_views = g_ptr_array_new();
185 RemoveView,
186 ([removed_views](auto engine, const FlutterRemoveViewInfo* info) {
187 g_ptr_array_add(removed_views, GINT_TO_POINTER(info->view_id));
188 return kSuccess;
189 }));
190
191 g_autoptr(GError) error = nullptr;
192 EXPECT_TRUE(fl_engine_start(engine, &error));
193
194 FlView* secondary_view = fl_view_new_for_engine(engine);
195
196 int64_t implicit_view_id = fl_view_get_id(implicit_view);
197 int64_t secondary_view_id = fl_view_get_id(secondary_view);
198
199 fl_gtk_widget_destroy(GTK_WIDGET(secondary_view));
200 fl_gtk_widget_destroy(GTK_WIDGET(implicit_view));
201
202 EXPECT_EQ(removed_views->len, 2u);
203 EXPECT_EQ(GPOINTER_TO_INT(g_ptr_array_index(removed_views, 0)),
204 secondary_view_id);
205 EXPECT_EQ(GPOINTER_TO_INT(g_ptr_array_index(removed_views, 1)),
206 implicit_view_id);
207}
208
209// Check views deregistered with errors works.
210TEST(FlViewTest, ViewDestroyError) {
212
213 g_autoptr(FlDartProject) project = fl_dart_project_new();
214 FlView* implicit_view = fl_view_new(project);
215
216 FlEngine* engine = fl_view_get_engine(implicit_view);
217
219 RemoveView, ([](auto engine, const FlutterRemoveViewInfo* info) {
220 return kInvalidArguments;
221 }));
222
223 g_autoptr(GError) error = nullptr;
224 EXPECT_TRUE(fl_engine_start(engine, &error));
225
226 FlView* secondary_view = fl_view_new_for_engine(engine);
227
228 fl_gtk_widget_destroy(GTK_WIDGET(secondary_view));
229 fl_gtk_widget_destroy(GTK_WIDGET(implicit_view));
230}
@ kInvalidArguments
Definition embedder.h:75
@ kSuccess
Definition embedder.h:73
int64_t FlutterViewId
Definition embedder.h:386
FlutterEngine engine
Definition main.cc:84
FlView * view
static void first_frame_cb(FlApplication *self, FlView *view)
g_autoptr(GMutexLocker) locker
return TRUE
G_MODULE_EXPORT FlDartProject * fl_dart_project_new()
FlutterEngineProcTable * fl_engine_get_embedder_api(FlEngine *self)
Definition fl_engine.cc:868
gboolean fl_engine_start(FlEngine *self, GError **error)
Definition fl_engine.cc:726
const uint8_t uint32_t uint32_t GError ** error
void fl_renderable_present_layers(FlRenderable *self, const FlutterLayer **layers, size_t layers_count)
G_MODULE_EXPORT FlView * fl_view_new_for_engine(FlEngine *engine)
Definition fl_view.cc:777
FlViewAccessible * fl_view_get_accessible(FlView *self)
Definition fl_view.cc:808
G_MODULE_EXPORT FlView * fl_view_new(FlDartProject *project)
Definition fl_view.cc:763
G_MODULE_EXPORT FlEngine * fl_view_get_engine(FlView *self)
Definition fl_view.cc:790
G_MODULE_EXPORT int64_t fl_view_get_id(FlView *self)
Definition fl_view.cc:796
G_BEGIN_DECLS FlutterViewId view_id
TEST(FlViewTest, GetEngine)
void fl_gtk_widget_destroy(GtkWidget *widget)
Definition mock_gtk.cc:269
GLogLevelFlags fl_get_received_gtk_log_levels()
Returns the recorded log levels.
void fl_ensure_gtk_init(GLogWriterFunc writer)
Ensures that GTK has been initialized and starts monitoring logs.
#define MOCK_ENGINE_PROC(proc, mock_impl)
FlutterAddViewCallback add_view_callback
Definition embedder.h:1117
FlutterViewId view_id
The identifier for the view to add. This must be unique.
Definition embedder.h:1097
FlutterEngineAddViewFnPtr AddView
Definition embedder.h:3748
FlutterEngineRemoveViewFnPtr RemoveView
Definition embedder.h:3749
FlutterViewId view_id
Definition embedder.h:1148
int32_t id
The unique identifier for this node.
Definition embedder.h:1613
A batch of updates to semantics nodes and custom actions.
Definition embedder.h:1796
size_t node_count
The number of semantics node updates.
Definition embedder.h:1800