Flutter Linux Embedder
fl_platform_handler_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 <gtk/gtk.h>
6 
10 #include "flutter/shell/platform/linux/testing/fl_mock_binary_messenger.h"
11 #include "flutter/shell/platform/linux/testing/fl_test.h"
12 
13 #include "flutter/shell/platform/linux/testing/linux_test.h"
14 #include "gmock/gmock.h"
15 #include "gtest/gtest.h"
16 
17 G_DECLARE_FINAL_TYPE(FlTestApplication,
18  fl_test_application,
19  FL,
20  TEST_APPLICATION,
21  GtkApplication)
22 
23 struct _FlTestApplication {
24  GtkApplication parent_instance;
25  gboolean* dispose_called;
26 };
27 
28 G_DEFINE_TYPE(FlTestApplication,
29  fl_test_application,
30  gtk_application_get_type())
31 
32 static void fl_test_application_startup(GApplication* application) {
33  G_APPLICATION_CLASS(fl_test_application_parent_class)->startup(application);
34 
35  // Add a window to this application, which will hold a reference to the
36  // application and stop it disposing. See
37  // https://gitlab.gnome.org/GNOME/gtk/-/issues/6190
38  gtk_application_window_new(GTK_APPLICATION(application));
39 }
40 
41 static void fl_test_application_activate(GApplication* application) {
42  G_APPLICATION_CLASS(fl_test_application_parent_class)->activate(application);
43 
44  g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new();
45  g_autoptr(FlPlatformHandler) handler =
46  fl_platform_handler_new(FL_BINARY_MESSENGER(messenger));
47  EXPECT_NE(handler, nullptr);
48 
49  // Request app exit.
50  gboolean called = FALSE;
53  fl_mock_binary_messenger_invoke_json_method(
54  messenger, "flutter/platform", "System.exitApplication", args,
55  [](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
56  gpointer user_data) {
57  gboolean* called = static_cast<gboolean*>(user_data);
58  *called = TRUE;
59 
60  EXPECT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response));
61 
62  g_autoptr(FlValue) expected_result = fl_value_new_map();
63  fl_value_set_string_take(expected_result, "response",
64  fl_value_new_string("exit"));
66  FL_METHOD_SUCCESS_RESPONSE(response)),
67  expected_result));
68  },
69  &called);
70  EXPECT_TRUE(called);
71 
72  fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
73 }
74 
75 static void fl_test_application_dispose(GObject* object) {
76  FlTestApplication* self = FL_TEST_APPLICATION(object);
77 
78  *self->dispose_called = true;
79 
80  G_OBJECT_CLASS(fl_test_application_parent_class)->dispose(object);
81 }
82 
83 static void fl_test_application_class_init(FlTestApplicationClass* klass) {
84  G_OBJECT_CLASS(klass)->dispose = fl_test_application_dispose;
85  G_APPLICATION_CLASS(klass)->startup = fl_test_application_startup;
86  G_APPLICATION_CLASS(klass)->activate = fl_test_application_activate;
87 }
88 
89 static void fl_test_application_init(FlTestApplication* self) {}
90 
91 FlTestApplication* fl_test_application_new(gboolean* dispose_called) {
92  FlTestApplication* self = FL_TEST_APPLICATION(
93  g_object_new(fl_test_application_get_type(), nullptr));
94 
95  // Don't try and register on D-Bus.
96  g_application_set_application_id(G_APPLICATION(self), "dev.flutter.GtkTest");
97  g_application_set_flags(G_APPLICATION(self), G_APPLICATION_NON_UNIQUE);
98 
99  // Added to stop compiler complaining about an unused function.
100  FL_IS_TEST_APPLICATION(self);
101 
102  self->dispose_called = dispose_called;
103 
104  return self;
105 }
106 
107 class FlPlatformHandlerTest : public flutter::testing::LinuxTest {
108  protected:
109  void SetUp() override {
110  messenger = fl_mock_binary_messenger_new();
111  handler = fl_platform_handler_new(FL_BINARY_MESSENGER(messenger));
112  }
113 
115  fl_binary_messenger_shutdown(FL_BINARY_MESSENGER(messenger));
116  g_clear_object(&handler);
117  g_clear_object(&messenger);
118  }
119 
120  FlMockBinaryMessenger* messenger = nullptr;
121  FlPlatformHandler* handler = nullptr;
122 };
123 
125  gboolean called = FALSE;
126  g_autoptr(FlValue) args = fl_value_new_string("SystemSoundType.alert");
127  fl_mock_binary_messenger_invoke_json_method(
128  messenger, "flutter/platform", "SystemSound.play", args,
129  [](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
130  gpointer user_data) {
131  gboolean* called = static_cast<gboolean*>(user_data);
132  *called = TRUE;
133 
134  EXPECT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response));
135 
136  g_autoptr(FlValue) expected_result = fl_value_new_null();
138  FL_METHOD_SUCCESS_RESPONSE(response)),
139  expected_result));
140  },
141  &called);
142  EXPECT_TRUE(called);
143 }
144 
145 TEST_F(FlPlatformHandlerTest, ExitApplication) {
146  // Indicate that the binding is initialized.
147  gboolean called = FALSE;
148  fl_mock_binary_messenger_invoke_json_method(
149  messenger, "flutter/platform", "System.initializationComplete", nullptr,
150  [](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
151  gpointer user_data) {
152  gboolean* called = static_cast<gboolean*>(user_data);
153  *called = TRUE;
154 
155  EXPECT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response));
156 
157  g_autoptr(FlValue) expected_result = fl_value_new_null();
159  FL_METHOD_SUCCESS_RESPONSE(response)),
160  expected_result));
161  },
162  &called);
163  EXPECT_TRUE(called);
164 
165  gboolean request_exit_called = FALSE;
166  fl_mock_binary_messenger_set_json_method_channel(
167  messenger, "flutter/platform",
168  [](FlMockBinaryMessenger* messenger, GTask* task, const gchar* name,
169  FlValue* args, gpointer user_data) {
170  gboolean* called = static_cast<gboolean*>(user_data);
171  *called = TRUE;
172 
173  EXPECT_STREQ(name, "System.requestAppExit");
174 
175  g_autoptr(FlValue) expected_args = fl_value_new_map();
176  fl_value_set_string_take(expected_args, "type",
177  fl_value_new_string("cancelable"));
178  EXPECT_TRUE(fl_value_equal(args, expected_args));
179 
180  // Cancel so it doesn't try and exit this app (i.e. the current test)
181  g_autoptr(FlValue) result = fl_value_new_map();
182  fl_value_set_string_take(result, "response",
183  fl_value_new_string("cancel"));
184  return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
185  },
186  &request_exit_called);
187 
189  fl_value_set_string_take(args, "type", fl_value_new_string("cancelable"));
190  fl_mock_binary_messenger_invoke_json_method(
191  messenger, "flutter/platform", "System.exitApplication", args,
192  [](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
193  gpointer user_data) {
194  EXPECT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response));
195 
196  g_autoptr(FlValue) expected_result = fl_value_new_map();
197  fl_value_set_string_take(expected_result, "response",
198  fl_value_new_string("cancel"));
200  FL_METHOD_SUCCESS_RESPONSE(response)),
201  expected_result));
202 
203  g_main_loop_quit(static_cast<GMainLoop*>(user_data));
204  },
205  loop);
206 
207  g_main_loop_run(loop);
208 
209  EXPECT_TRUE(request_exit_called);
210 }
211 
212 TEST_F(FlPlatformHandlerTest, ExitApplicationDispose) {
213  gtk_init(0, nullptr);
214 
215  gboolean dispose_called = false;
216  FlTestApplication* application = fl_test_application_new(&dispose_called);
217 
218  // Run the application, it will quit after startup.
219  g_application_run(G_APPLICATION(application), 0, nullptr);
220 
221  EXPECT_FALSE(dispose_called);
222  g_object_unref(application);
223  EXPECT_TRUE(dispose_called);
224 }
FlMockBinaryMessenger * messenger
g_autoptr(FlEngine) engine
const char FlTextDirection FlAssertiveness gpointer user_data
void fl_binary_messenger_shutdown(FlBinaryMessenger *self)
return TRUE
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
G_MODULE_EXPORT FlMethodSuccessResponse * fl_method_success_response_new(FlValue *result)
G_MODULE_EXPORT FlValue * fl_method_success_response_get_result(FlMethodSuccessResponse *self)
FlPlatformHandler * fl_platform_handler_new(FlBinaryMessenger *messenger)
static void fl_test_application_activate(GApplication *application)
static void fl_test_application_dispose(GObject *object)
TEST_F(FlPlatformHandlerTest, PlaySound)
static void fl_test_application_init(FlTestApplication *self)
G_DECLARE_FINAL_TYPE(FlTestApplication, fl_test_application, FL, TEST_APPLICATION, GtkApplication) struct _FlTestApplication
FlTestApplication * fl_test_application_new(gboolean *dispose_called)
G_DEFINE_TYPE(FlTestApplication, fl_test_application, gtk_application_get_type()) static void fl_test_application_startup(GApplication *application)
static void fl_test_application_class_init(FlTestApplicationClass *klass)
G_MODULE_EXPORT void fl_value_set_string_take(FlValue *self, const gchar *key, FlValue *value)
Definition: fl_value.cc:650
G_MODULE_EXPORT FlValue * fl_value_new_string(const gchar *value)
Definition: fl_value.cc:276
G_MODULE_EXPORT FlValue * fl_value_new_null()
Definition: fl_value.cc:251
G_MODULE_EXPORT bool fl_value_equal(FlValue *a, FlValue *b)
Definition: fl_value.cc:471
G_MODULE_EXPORT FlValue * fl_value_new_map()
Definition: fl_value.cc:366
typedefG_BEGIN_DECLS struct _FlValue FlValue
Definition: fl_value.h:42