Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
fl_platform_plugin_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
7#include "flutter/shell/platform/linux/fl_binary_messenger_private.h"
8#include "flutter/shell/platform/linux/fl_method_codec_private.h"
9#include "flutter/shell/platform/linux/fl_platform_plugin.h"
10#include "flutter/shell/platform/linux/public/flutter_linux/fl_json_method_codec.h"
11#include "flutter/shell/platform/linux/public/flutter_linux/fl_method_codec.h"
12#include "flutter/shell/platform/linux/testing/fl_test.h"
13#include "flutter/shell/platform/linux/testing/mock_binary_messenger.h"
14#include "flutter/testing/testing.h"
15
16#include "gmock/gmock.h"
17#include "gtest/gtest.h"
18
19MATCHER_P(SuccessResponse, result, "") {
20 g_autoptr(FlJsonMethodCodec) codec = fl_json_method_codec_new();
21 g_autoptr(FlMethodResponse) response =
22 fl_method_codec_decode_response(FL_METHOD_CODEC(codec), arg, nullptr);
23 if (fl_value_equal(fl_method_response_get_result(response, nullptr),
24 result)) {
25 return true;
26 }
27 *result_listener << ::testing::PrintToString(response);
28 return false;
29}
30
32 public:
33 using is_gtest_matcher = void;
34
35 explicit MethodCallMatcher(::testing::Matcher<std::string> name,
36 ::testing::Matcher<FlValue*> args)
37 : name_(std::move(name)), args_(std::move(args)) {}
38
40 ::testing::MatchResultListener* result_listener) const {
41 g_autoptr(FlJsonMethodCodec) codec = fl_json_method_codec_new();
42 g_autoptr(GError) error = nullptr;
43 g_autofree gchar* name = nullptr;
44 g_autoptr(FlValue) args = nullptr;
46 FL_METHOD_CODEC(codec), method_call, &name, &args, &error);
47 if (!result) {
48 *result_listener << ::testing::PrintToString(error->message);
49 return false;
50 }
51 if (!name_.MatchAndExplain(name, result_listener)) {
52 *result_listener << " where the name doesn't match: \"" << name << "\"";
53 return false;
54 }
55 if (!args_.MatchAndExplain(args, result_listener)) {
56 *result_listener << " where the args don't match: "
57 << ::testing::PrintToString(args);
58 return false;
59 }
60 return true;
61 }
62
63 void DescribeTo(std::ostream* os) const {
64 *os << "method name ";
65 name_.DescribeTo(os);
66 *os << " and args ";
67 args_.DescribeTo(os);
68 }
69
70 void DescribeNegationTo(std::ostream* os) const {
71 *os << "method name ";
72 name_.DescribeNegationTo(os);
73 *os << " or args ";
74 args_.DescribeNegationTo(os);
75 }
76
77 private:
78 ::testing::Matcher<std::string> name_;
79 ::testing::Matcher<FlValue*> args_;
80};
81
82static ::testing::Matcher<GBytes*> MethodCall(
83 const std::string& name,
84 ::testing::Matcher<FlValue*> args) {
85 return MethodCallMatcher(::testing::StrEq(name), std::move(args));
86}
87
88MATCHER_P(FlValueEq, value, "equal to " + ::testing::PrintToString(value)) {
89 return fl_value_equal(arg, value);
90}
91
92G_DECLARE_FINAL_TYPE(FlTestApplication,
93 fl_test_application,
94 FL,
95 TEST_APPLICATION,
96 GtkApplication)
97
98struct _FlTestApplication {
99 GtkApplication parent_instance;
100 gboolean* dispose_called;
101};
102
103G_DEFINE_TYPE(FlTestApplication,
104 fl_test_application,
105 gtk_application_get_type())
106
107static void fl_test_application_startup(GApplication* application) {
108 G_APPLICATION_CLASS(fl_test_application_parent_class)->startup(application);
109
110 // Add a window to this application, which will hold a reference to the
111 // application and stop it disposing. See
112 // https://gitlab.gnome.org/GNOME/gtk/-/issues/6190
113 gtk_application_window_new(GTK_APPLICATION(application));
114}
115
116static void fl_test_application_activate(GApplication* application) {
117 G_APPLICATION_CLASS(fl_test_application_parent_class)->activate(application);
118
119 ::testing::NiceMock<flutter::testing::MockBinaryMessenger> messenger;
120 g_autoptr(FlPlatformPlugin) plugin = fl_platform_plugin_new(messenger);
121 EXPECT_NE(plugin, nullptr);
122 g_autoptr(FlJsonMethodCodec) codec = fl_json_method_codec_new();
123
124 g_autoptr(FlValue) exit_result = fl_value_new_map();
125 fl_value_set_string_take(exit_result, "response",
126 fl_value_new_string("exit"));
127 EXPECT_CALL(messenger,
129 ::testing::Eq<FlBinaryMessenger*>(messenger), ::testing::_,
130 SuccessResponse(exit_result), ::testing::_))
131 .WillOnce(::testing::Return(true));
132
133 // Request app exit.
134 g_autoptr(FlValue) args = fl_value_new_map();
137 FL_METHOD_CODEC(codec), "System.exitApplication", args, nullptr);
138 messenger.ReceiveMessage("flutter/platform", message);
139}
140
141static void fl_test_application_dispose(GObject* object) {
142 FlTestApplication* self = FL_TEST_APPLICATION(object);
143
144 *self->dispose_called = true;
145
146 G_OBJECT_CLASS(fl_test_application_parent_class)->dispose(object);
147}
148
149static void fl_test_application_class_init(FlTestApplicationClass* klass) {
150 G_OBJECT_CLASS(klass)->dispose = fl_test_application_dispose;
151 G_APPLICATION_CLASS(klass)->startup = fl_test_application_startup;
152 G_APPLICATION_CLASS(klass)->activate = fl_test_application_activate;
153}
154
155static void fl_test_application_init(FlTestApplication* self) {}
156
157FlTestApplication* fl_test_application_new(gboolean* dispose_called) {
158 FlTestApplication* self = FL_TEST_APPLICATION(
159 g_object_new(fl_test_application_get_type(), nullptr));
160
161 // Don't try and register on D-Bus.
162 g_application_set_application_id(G_APPLICATION(self), "dev.flutter.GtkTest");
163 g_application_set_flags(G_APPLICATION(self), G_APPLICATION_NON_UNIQUE);
164
165 // Added to stop compiler complaining about an unused function.
166 FL_IS_TEST_APPLICATION(self);
167
168 self->dispose_called = dispose_called;
169
170 return self;
171}
172
173TEST(FlPlatformPluginTest, PlaySound) {
174 ::testing::NiceMock<flutter::testing::MockBinaryMessenger> messenger;
175
176 g_autoptr(FlPlatformPlugin) plugin = fl_platform_plugin_new(messenger);
177 EXPECT_NE(plugin, nullptr);
178
179 g_autoptr(FlValue) args = fl_value_new_string("SystemSoundType.alert");
180 g_autoptr(FlJsonMethodCodec) codec = fl_json_method_codec_new();
182 FL_METHOD_CODEC(codec), "SystemSound.play", args, nullptr);
183
184 g_autoptr(FlValue) null = fl_value_new_null();
185 EXPECT_CALL(messenger, fl_binary_messenger_send_response(
186 ::testing::Eq<FlBinaryMessenger*>(messenger),
187 ::testing::_, SuccessResponse(null), ::testing::_))
188 .WillOnce(::testing::Return(true));
189
190 messenger.ReceiveMessage("flutter/platform", message);
191}
192
193TEST(FlPlatformPluginTest, ExitApplication) {
194 ::testing::NiceMock<flutter::testing::MockBinaryMessenger> messenger;
195
196 g_autoptr(FlPlatformPlugin) plugin = fl_platform_plugin_new(messenger);
197 EXPECT_NE(plugin, nullptr);
198 g_autoptr(FlJsonMethodCodec) codec = fl_json_method_codec_new();
199
200 g_autoptr(FlValue) null = fl_value_new_null();
201 ON_CALL(messenger, fl_binary_messenger_send_response(
202 ::testing::Eq<FlBinaryMessenger*>(messenger),
203 ::testing::_, SuccessResponse(null), ::testing::_))
204 .WillByDefault(testing::Return(TRUE));
205
206 // Indicate that the binding is initialized.
207 g_autoptr(GError) error = nullptr;
208 g_autoptr(GBytes) init_message = fl_method_codec_encode_method_call(
209 FL_METHOD_CODEC(codec), "System.initializationComplete", nullptr, &error);
210 messenger.ReceiveMessage("flutter/platform", init_message);
211
212 g_autoptr(FlValue) request_args = fl_value_new_map();
213 fl_value_set_string_take(request_args, "type",
214 fl_value_new_string("cancelable"));
215 EXPECT_CALL(messenger,
217 ::testing::Eq<FlBinaryMessenger*>(messenger),
218 ::testing::StrEq("flutter/platform"),
219 MethodCall("System.requestAppExit", FlValueEq(request_args)),
220 ::testing::_, ::testing::_, ::testing::_));
221
222 g_autoptr(FlValue) args = fl_value_new_map();
223 fl_value_set_string_take(args, "type", fl_value_new_string("cancelable"));
225 FL_METHOD_CODEC(codec), "System.exitApplication", args, nullptr);
226 messenger.ReceiveMessage("flutter/platform", message);
227}
228
229TEST(FlPlatformPluginTest, ExitApplicationDispose) {
230 gtk_init(0, nullptr);
231
232 gboolean dispose_called = false;
233 FlTestApplication* application = fl_test_application_new(&dispose_called);
234
235 // Run the application, it will quit after startup.
236 g_application_run(G_APPLICATION(application), 0, nullptr);
237
238 EXPECT_FALSE(dispose_called);
239 g_object_unref(application);
240 EXPECT_TRUE(dispose_called);
241}
#define TEST(S, s, D, expected)
bool MatchAndExplain(GBytes *method_call, ::testing::MatchResultListener *result_listener) const
MethodCallMatcher(::testing::Matcher< std::string > name, ::testing::Matcher< FlValue * > args)
void DescribeTo(std::ostream *os) const
void DescribeNegationTo(std::ostream *os) const
G_MODULE_EXPORT void fl_binary_messenger_send_on_channel(FlBinaryMessenger *self, const gchar *channel, GBytes *message, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
G_MODULE_EXPORT gboolean fl_binary_messenger_send_response(FlBinaryMessenger *self, FlBinaryMessengerResponseHandle *response_handle, GBytes *response, GError **error)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
G_MODULE_EXPORT FlJsonMethodCodec * fl_json_method_codec_new()
G_BEGIN_DECLS G_MODULE_EXPORT FlMethodCall * method_call
FlMethodResponse * fl_method_codec_decode_response(FlMethodCodec *self, GBytes *message, GError **error)
gboolean fl_method_codec_decode_method_call(FlMethodCodec *self, GBytes *message, gchar **name, FlValue **args, GError **error)
GBytes * fl_method_codec_encode_method_call(FlMethodCodec *self, const gchar *name, FlValue *args, GError **error)
G_MODULE_EXPORT FlValue * fl_method_response_get_result(FlMethodResponse *self, GError **error)
const uint8_t uint32_t uint32_t GError ** error
FlPlatformPlugin * fl_platform_plugin_new(FlBinaryMessenger *messenger)
MATCHER_P(SuccessResponse, result, "")
static ::testing::Matcher< GBytes * > MethodCall(const std::string &name, ::testing::Matcher< FlValue * > args)
static void fl_test_application_activate(GApplication *application)
static void fl_test_application_dispose(GObject *object)
FlTestApplication * fl_test_application_new(gboolean *dispose_called)
static void fl_test_application_init(FlTestApplication *self)
G_DECLARE_FINAL_TYPE(FlTestApplication, fl_test_application, FL, TEST_APPLICATION, GtkApplication) struct _FlTestApplication
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)
uint8_t value
GAsyncResult * result
G_MODULE_EXPORT FlValue * fl_value_new_map()
Definition fl_value.cc:366
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_null()
Definition fl_value.cc:251
G_MODULE_EXPORT FlValue * fl_value_new_string(const gchar *value)
Definition fl_value.cc:276
G_MODULE_EXPORT bool fl_value_equal(FlValue *a, FlValue *b)
Definition fl_value.cc:471
typedefG_BEGIN_DECLS struct _FlValue FlValue
Definition fl_value.h:42
const char * name
Definition fuchsia.cc:50
Win32Message message
Definition ref_ptr.h:256
#define EXPECT_TRUE(handle)
Definition unit_test.h:685