Flutter Linux Embedder
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 
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 
19 MATCHER_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 
82 static ::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 
88 MATCHER_P(FlValueEq, value, "equal to " + ::testing::PrintToString(value)) {
89  return fl_value_equal(arg, value);
90 }
91 
92 G_DECLARE_FINAL_TYPE(FlTestApplication,
93  fl_test_application,
94  FL,
95  TEST_APPLICATION,
96  GtkApplication)
97 
98 struct _FlTestApplication {
99  GtkApplication parent_instance;
100  gboolean* dispose_called;
101 };
102 
103 G_DEFINE_TYPE(FlTestApplication,
104  fl_test_application,
105  gtk_application_get_type())
106 
107 static 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 
116 static 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();
135  fl_value_set_string_take(args, "type", fl_value_new_string("required"));
136  g_autoptr(GBytes) message = fl_method_codec_encode_method_call(
137  FL_METHOD_CODEC(codec), "System.exitApplication", args, nullptr);
138  messenger.ReceiveMessage("flutter/platform", message);
139 }
140 
141 static 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 
149 static 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 
155 static void fl_test_application_init(FlTestApplication* self) {}
156 
157 FlTestApplication* 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 
173 TEST(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();
181  g_autoptr(GBytes) message = fl_method_codec_encode_method_call(
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 
193 TEST(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"));
224  g_autoptr(GBytes) message = fl_method_codec_encode_method_call(
225  FL_METHOD_CODEC(codec), "System.exitApplication", args, nullptr);
226  messenger.ReceiveMessage("flutter/platform", message);
227 }
228 
229 TEST(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 }
fl_json_method_codec_new
G_MODULE_EXPORT FlJsonMethodCodec * fl_json_method_codec_new()
Definition: fl_json_method_codec.cc:205
fl_method_codec_encode_method_call
GBytes * fl_method_codec_encode_method_call(FlMethodCodec *self, const gchar *name, FlValue *args, GError **error)
Definition: fl_method_codec.cc:16
MethodCallMatcher::MethodCallMatcher
MethodCallMatcher(::testing::Matcher< std::string > name, ::testing::Matcher< FlValue * > args)
Definition: fl_platform_plugin_test.cc:35
MethodCallMatcher::DescribeNegationTo
void DescribeNegationTo(std::ostream *os) const
Definition: fl_platform_plugin_test.cc:70
fl_value_set_string_take
G_MODULE_EXPORT void fl_value_set_string_take(FlValue *self, const gchar *key, FlValue *value)
Definition: fl_value.cc:650
MethodCall
static ::testing::Matcher< GBytes * > MethodCall(const std::string &name, ::testing::Matcher< FlValue * > args)
Definition: fl_platform_plugin_test.cc:82
FlValue
typedefG_BEGIN_DECLS struct _FlValue FlValue
Definition: fl_value.h:42
fl_platform_plugin_new
FlPlatformPlugin * fl_platform_plugin_new(FlBinaryMessenger *messenger)
Definition: fl_platform_plugin.cc:402
fl_value_new_null
G_MODULE_EXPORT FlValue * fl_value_new_null()
Definition: fl_value.cc:251
fl_test_application_dispose
static void fl_test_application_dispose(GObject *object)
Definition: fl_platform_plugin_test.cc:141
MATCHER_P
MATCHER_P(SuccessResponse, result, "")
Definition: fl_platform_plugin_test.cc:19
fl_method_response_get_result
G_MODULE_EXPORT FlValue * fl_method_response_get_result(FlMethodResponse *self, GError **error)
Definition: fl_method_response.cc:82
TEST
TEST(FlPlatformPluginTest, PlaySound)
Definition: fl_platform_plugin_test.cc:173
fl_value_new_map
G_MODULE_EXPORT FlValue * fl_value_new_map()
Definition: fl_value.cc:366
MethodCallMatcher::DescribeTo
void DescribeTo(std::ostream *os) const
Definition: fl_platform_plugin_test.cc:63
G_DEFINE_TYPE
G_DEFINE_TYPE(FlTestApplication, fl_test_application, gtk_application_get_type()) static void fl_test_application_startup(GApplication *application)
Definition: fl_platform_plugin_test.cc:103
method_call
G_BEGIN_DECLS G_MODULE_EXPORT FlMethodCall * method_call
Definition: fl_method_channel.h:120
fl_test_application_activate
static void fl_test_application_activate(GApplication *application)
Definition: fl_platform_plugin_test.cc:116
fl_method_codec_decode_method_call
gboolean fl_method_codec_decode_method_call(FlMethodCodec *self, GBytes *message, gchar **name, FlValue **args, GError **error)
Definition: fl_method_codec.cc:27
fl_test_application_new
FlTestApplication * fl_test_application_new(gboolean *dispose_called)
Definition: fl_platform_plugin_test.cc:157
MethodCallMatcher::is_gtest_matcher
void is_gtest_matcher
Definition: fl_platform_plugin_test.cc:33
TRUE
return TRUE
Definition: fl_pixel_buffer_texture_test.cc:53
fl_method_codec_decode_response
FlMethodResponse * fl_method_codec_decode_response(FlMethodCodec *self, GBytes *message, GError **error)
Definition: fl_method_codec.cc:62
fl_method_codec.h
FL
FL
Definition: fl_binary_messenger.cc:27
MethodCallMatcher::MatchAndExplain
bool MatchAndExplain(GBytes *method_call, ::testing::MatchResultListener *result_listener) const
Definition: fl_platform_plugin_test.cc:39
fl_value_equal
G_MODULE_EXPORT bool fl_value_equal(FlValue *a, FlValue *b)
Definition: fl_value.cc:471
fl_test_application_init
static void fl_test_application_init(FlTestApplication *self)
Definition: fl_platform_plugin_test.cc:155
fl_binary_messenger_private.h
result
GAsyncResult * result
Definition: fl_text_input_plugin.cc:106
MethodCallMatcher
Definition: fl_platform_plugin_test.cc:31
fl_test_application_class_init
static void fl_test_application_class_init(FlTestApplicationClass *klass)
Definition: fl_platform_plugin_test.cc:149
G_DECLARE_FINAL_TYPE
G_DECLARE_FINAL_TYPE(FlTestApplication, fl_test_application, FL, TEST_APPLICATION, GtkApplication) struct _FlTestApplication
Definition: fl_platform_plugin_test.cc:92
args
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
Definition: fl_event_channel.h:89
error
const uint8_t uint32_t uint32_t GError ** error
Definition: fl_pixel_buffer_texture_test.cc:40
fl_platform_plugin.h
fl_binary_messenger_send_response
G_MODULE_EXPORT gboolean fl_binary_messenger_send_response(FlBinaryMessenger *self, FlBinaryMessengerResponseHandle *response_handle, GBytes *response, GError **error)
Definition: fl_binary_messenger.cc:430
fl_method_codec_private.h
value
uint8_t value
Definition: fl_standard_message_codec.cc:36
fl_binary_messenger_send_on_channel
G_MODULE_EXPORT void fl_binary_messenger_send_on_channel(FlBinaryMessenger *self, const gchar *channel, GBytes *message, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
Definition: fl_binary_messenger.cc:443
fl_json_method_codec.h
fl_value_new_string
G_MODULE_EXPORT FlValue * fl_value_new_string(const gchar *value)
Definition: fl_value.cc:276