6#include "gtest/gtest.h"
11#include "flutter/shell/platform/embedder/embedder.h"
12#include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h"
13#include "flutter/shell/platform/linux/fl_binary_messenger_private.h"
14#include "flutter/shell/platform/linux/fl_engine_private.h"
15#include "flutter/shell/platform/linux/public/flutter_linux/fl_binary_messenger.h"
16#include "flutter/shell/platform/linux/public/flutter_linux/fl_method_channel.h"
17#include "flutter/shell/platform/linux/public/flutter_linux/fl_standard_method_codec.h"
18#include "flutter/shell/platform/linux/testing/fl_test.h"
19#include "flutter/shell/platform/linux/testing/mock_binary_messenger_response_handle.h"
20#include "flutter/shell/platform/linux/testing/mock_renderer.h"
23 fl_fake_binary_messenger,
25 FAKE_BINARY_MESSENGER,
28struct _FlFakeBinaryMessenger {
29 GObject parent_instance;
32 GAsyncReadyCallback send_callback;
33 gpointer send_callback_user_data;
35 gpointer message_handler_user_data;
39 FlBinaryMessengerInterface* iface);
42 FlFakeBinaryMessenger,
43 fl_fake_binary_messenger,
45 G_IMPLEMENT_INTERFACE(fl_binary_messenger_get_type(),
48static void fl_fake_binary_messenger_class_init(
49 FlFakeBinaryMessengerClass* klass) {}
52 FlFakeBinaryMessenger*
self = FL_FAKE_BINARY_MESSENGER(
user_data);
54 const char*
text =
"Marco!";
57 FL_BINARY_MESSENGER_RESPONSE_HANDLE(
59 self->message_handler_user_data);
65 FlBinaryMessenger* messenger,
69 GDestroyNotify destroy_notify) {
70 FlFakeBinaryMessenger*
self = FL_FAKE_BINARY_MESSENGER(messenger);
72 EXPECT_STREQ(channel,
"CHANNEL");
75 self->message_handler = handler;
81 FlBinaryMessengerResponseHandle* response_handle,
84 FlFakeBinaryMessenger*
self = FL_FAKE_BINARY_MESSENGER(messenger);
86 EXPECT_TRUE(FL_IS_MOCK_BINARY_MESSENGER_RESPONSE_HANDLE(response_handle));
88 g_autofree gchar*
text =
89 g_strndup(
static_cast<const gchar*
>(g_bytes_get_data(response,
nullptr)),
90 g_bytes_get_size(response));
91 EXPECT_STREQ(
text,
"Polo!");
93 g_main_loop_quit(
self->loop);
99 FlFakeBinaryMessenger*
self = FL_FAKE_BINARY_MESSENGER(
user_data);
101 self->send_callback(G_OBJECT(
self), NULL,
self->send_callback_user_data);
107 const gchar* channel,
109 GCancellable* cancellable,
112 FlFakeBinaryMessenger*
self = FL_FAKE_BINARY_MESSENGER(messenger);
114 EXPECT_STREQ(channel,
"CHANNEL");
115 g_autofree gchar*
text =
116 g_strndup(
static_cast<const gchar*
>(g_bytes_get_data(
message,
nullptr)),
118 EXPECT_STREQ(
text,
"Marco!");
129 const char*
text =
"Polo!";
130 return g_bytes_new(
text, strlen(
text));
134 const gchar* channel,
140 const gchar* channel,
146 FlBinaryMessengerInterface* iface) {
158 FlFakeBinaryMessenger*
self = FL_FAKE_BINARY_MESSENGER(
159 g_object_new(fl_fake_binary_messenger_get_type(), NULL));
161 return FL_BINARY_MESSENGER(
self);
168 g_autoptr(GError)
error =
nullptr;
172 EXPECT_EQ(
error,
nullptr);
174 g_autofree gchar*
text =
175 g_strndup(
static_cast<const gchar*
>(g_bytes_get_data(
message,
nullptr)),
177 EXPECT_STREQ(
text,
"Polo!");
179 g_main_loop_quit(
static_cast<GMainLoop*
>(
user_data));
183TEST(FlBinaryMessengerTest, FakeMessengerSend) {
184 g_autoptr(GMainLoop) loop = g_main_loop_new(
nullptr, 0);
187 EXPECT_TRUE(FL_IS_FAKE_BINARY_MESSENGER(messenger));
189 const char*
text =
"Marco!";
195 g_main_loop_run(loop);
200 const gchar* channel,
202 FlBinaryMessengerResponseHandle* response_handle,
204 EXPECT_STREQ(channel,
"CHANNEL");
207 g_autofree gchar*
text =
208 g_strndup(
static_cast<const gchar*
>(g_bytes_get_data(
message,
nullptr)),
210 EXPECT_STREQ(
text,
"Marco!");
212 const char* response_text =
"Polo!";
213 g_autoptr(GBytes) response =
214 g_bytes_new(response_text, strlen(response_text));
215 g_autoptr(GError)
error =
nullptr;
218 EXPECT_EQ(
error,
nullptr);
222TEST(FlBinaryMessengerTest, FakeMessengerReceive) {
223 g_autoptr(GMainLoop) loop = g_main_loop_new(
nullptr, 0);
226 EXPECT_TRUE(FL_IS_FAKE_BINARY_MESSENGER(messenger));
232 g_main_loop_run(loop);
236TEST(FlBinaryMessengerTest, SendNullptrMessage) {
244TEST(FlBinaryMessengerTest, SendEmptyMessage) {
247 g_autoptr(GBytes)
message = g_bytes_new(
nullptr, 0);
256 g_autoptr(GError)
error =
nullptr;
260 EXPECT_EQ(
error,
nullptr);
262 g_autofree gchar*
text =
263 g_strndup(
static_cast<const gchar*
>(g_bytes_get_data(
message,
nullptr)),
265 EXPECT_STREQ(
text,
"Hello World!");
267 g_main_loop_quit(
static_cast<GMainLoop*
>(
user_data));
272 g_autoptr(GMainLoop) loop = g_main_loop_new(
nullptr, 0);
276 const char*
text =
"Hello World!";
282 g_main_loop_run(loop);
289 g_autoptr(GError)
error =
nullptr;
293 EXPECT_EQ(
error,
nullptr);
295 EXPECT_EQ(g_bytes_get_size(
message),
static_cast<gsize
>(0));
297 g_main_loop_quit(
static_cast<GMainLoop*
>(
user_data));
301TEST(FlBinaryMessengerTest, NullptrResponse) {
302 g_autoptr(GMainLoop) loop = g_main_loop_new(
nullptr, 0);
306 const char*
text =
"Hello World!";
313 g_main_loop_run(loop);
320 g_autoptr(GError)
error =
nullptr;
324 EXPECT_NE(
error,
nullptr);
326 g_main_loop_quit(
static_cast<GMainLoop*
>(
user_data));
330TEST(FlBinaryMessengerTest, SendFailure) {
331 g_autoptr(GMainLoop) loop = g_main_loop_new(
nullptr, 0);
339 g_main_loop_run(loop);
344 const gchar* channel,
346 FlBinaryMessengerResponseHandle* response_handle,
349 g_autofree gchar*
text =
350 g_strndup(
static_cast<const gchar*
>(g_bytes_get_data(
message,
nullptr)),
352 EXPECT_STREQ(
text,
"Marco!");
354 const char* response_text =
"Polo!";
355 g_autoptr(GBytes) response =
356 g_bytes_new(response_text, strlen(response_text));
357 g_autoptr(GError)
error =
nullptr;
360 EXPECT_EQ(
error,
nullptr);
366 const gchar* channel,
368 FlBinaryMessengerResponseHandle* response_handle,
371 g_autofree gchar*
text =
372 g_strndup(
static_cast<const gchar*
>(g_bytes_get_data(
message,
nullptr)),
374 EXPECT_STREQ(
text,
"Polo!");
379 g_main_loop_quit(
static_cast<GMainLoop*
>(
user_data));
383TEST(FlBinaryMessengerTest, ReceiveMessage) {
384 g_autoptr(GMainLoop) loop = g_main_loop_new(
nullptr, 0);
391 messenger,
"test/messages",
message_cb,
nullptr,
nullptr);
395 messenger,
"test/responses",
response_cb, loop,
nullptr);
398 const char*
text =
"Marco!";
401 nullptr,
nullptr,
nullptr);
404 g_main_loop_run(loop);
421 ([&called, old_handler](
auto engine,
424 if (strcmp(
message->channel,
"dev.flutter/channel-buffers") != 0) {
425 return old_handler(engine, message);
433 const int expected_message_size = 29;
434 EXPECT_EQ(
message->message_size,
435 static_cast<size_t>(expected_message_size));
436 int expected[expected_message_size] = {
437 7, 6, 114, 101, 115, 105, 122, 101, 12, 2,
438 7, 12, 102, 108, 117, 116, 116, 101, 114, 47,
439 116, 101, 115, 116, 3, 3, 0, 0, 0};
440 for (
size_t i = 0;
i < expected_message_size;
i++) {
441 EXPECT_EQ(
message->message[
i], expected[
i]);
447 g_autoptr(GError)
error =
nullptr;
449 EXPECT_EQ(
error,
nullptr);
458TEST(FlBinaryMessengerTest, WarnsOnOverflowChannel) {
468 ([&called, old_handler](
auto engine,
471 if (strcmp(
message->channel,
"dev.flutter/channel-buffers") != 0) {
472 return old_handler(engine, message);
480 const int expected_message_size = 27;
481 EXPECT_EQ(
message->message_size,
482 static_cast<size_t>(expected_message_size));
483 int expected[expected_message_size] = {
484 7, 8, 111, 118, 101, 114, 102, 108, 111, 119, 12, 2, 7, 12,
485 102, 108, 117, 116, 116, 101, 114, 47, 116, 101, 115, 116, 1};
486 for (
size_t i = 0;
i < expected_message_size;
i++) {
487 EXPECT_EQ(
message->message[
i], expected[
i]);
493 g_autoptr(GError)
error =
nullptr;
495 EXPECT_EQ(
error,
nullptr);
505 g_main_loop_quit(
static_cast<GMainLoop*
>(
user_data));
511TEST(FlBinaryMessengerTest, ControlChannelErrorResponse) {
512 g_autoptr(GMainLoop) loop = g_main_loop_new(
nullptr, 0);
516 g_autoptr(GError)
error =
nullptr;
518 EXPECT_EQ(
error,
nullptr);
528 ([&called, old_handler, loop](
auto engine,
531 if (strcmp(
message->channel,
"dev.flutter/channel-buffers") != 0) {
532 return old_handler(engine, message);
551 g_main_loop_run(loop);
565 GMainLoop* loop =
info->loop;
567 g_object_unref(
info->messenger);
568 g_object_unref(
info->response_handle);
571 g_main_loop_quit(
static_cast<GMainLoop*
>(loop));
573 return G_SOURCE_REMOVE;
589 FlBinaryMessenger* messenger,
590 const gchar* channel,
592 FlBinaryMessengerResponseHandle* response_handle,
599 info->messenger = FL_BINARY_MESSENGER(g_object_ref(messenger));
600 info->response_handle =
601 FL_BINARY_MESSENGER_RESPONSE_HANDLE(g_object_ref(response_handle));
607TEST(FlBinaryMessengerTest, RespondOnBackgroundThread) {
608 g_autoptr(GMainLoop) loop = g_main_loop_new(
nullptr, 0);
615 messenger,
"test/messages",
message_cb,
nullptr,
nullptr);
622 const char*
text =
"Marco!";
625 nullptr,
nullptr,
nullptr);
628 g_main_loop_run(loop);
632 *
static_cast<gboolean*
>(was_called) =
TRUE;
635TEST(FlBinaryMessengerTest, DeletingEngineClearsHandlers) {
638 gboolean was_killed =
FALSE;
647 ASSERT_TRUE(was_killed);
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
for(const auto glyph :glyphs)
FlutterEngineResult(* FlutterEngineSendPlatformMessageFnPtr)(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterPlatformMessage *message)
G_MODULE_EXPORT GBytes * fl_binary_messenger_send_on_channel_finish(FlBinaryMessenger *self, GAsyncResult *result, GError **error)
G_MODULE_EXPORT void fl_binary_messenger_resize_channel(FlBinaryMessenger *self, const gchar *channel, int64_t new_size)
G_MODULE_EXPORT void fl_binary_messenger_set_message_handler_on_channel(FlBinaryMessenger *self, const gchar *channel, FlBinaryMessengerMessageHandler handler, gpointer user_data, GDestroyNotify destroy_notify)
G_MODULE_EXPORT void fl_binary_messenger_send_on_channel(FlBinaryMessenger *self, const gchar *channel, GBytes *message, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
FlBinaryMessenger * fl_binary_messenger_new(FlEngine *engine)
G_MODULE_EXPORT gboolean fl_binary_messenger_send_response(FlBinaryMessenger *self, FlBinaryMessengerResponseHandle *response_handle, GBytes *response, GError **error)
G_MODULE_EXPORT void fl_binary_messenger_set_warns_on_channel_overflow(FlBinaryMessenger *self, const gchar *channel, bool warns)
G_MODULE_EXPORT GObject typedef void(* FlBinaryMessengerMessageHandler)(FlBinaryMessenger *messenger, const gchar *channel, GBytes *message, FlBinaryMessengerResponseHandle *response_handle, gpointer user_data)
static void resize_channel(FlBinaryMessenger *messenger, const gchar *channel, int64_t new_size)
static void send_on_channel(FlBinaryMessenger *messenger, const gchar *channel, GBytes *message, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
static gboolean cleanup_responds_on_background_thread_info(gpointer user_data)
static void message_cb(FlBinaryMessenger *messenger, const gchar *channel, GBytes *message, FlBinaryMessengerResponseHandle *response_handle, gpointer user_data)
static void fl_fake_binary_messenger_init(FlFakeBinaryMessenger *self)
static void response_cb(FlBinaryMessenger *messenger, const gchar *channel, GBytes *message, FlBinaryMessengerResponseHandle *response_handle, gpointer user_data)
static void set_message_handler_on_channel(FlBinaryMessenger *messenger, const gchar *channel, FlBinaryMessengerMessageHandler handler, gpointer user_data, GDestroyNotify destroy_notify)
static gboolean send_response(FlBinaryMessenger *messenger, FlBinaryMessengerResponseHandle *response_handle, GBytes *response, GError **error)
G_DEFINE_TYPE_WITH_CODE(FlFakeBinaryMessenger, fl_fake_binary_messenger, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE(fl_binary_messenger_get_type(), fl_fake_binary_messenger_iface_init)) static void fl_fake_binary_messenger_class_init(FlFakeBinaryMessengerClass *klass)
TEST(FlBinaryMessengerTest, FakeMessengerSend)
static void * response_from_thread_main(void *user_data)
static gboolean send_ready_cb(gpointer user_data)
static gboolean send_message_cb(gpointer user_data)
static void set_warns_on_channel_overflow(FlBinaryMessenger *messenger, const gchar *channel, bool warns)
static void nullptr_response_cb(GObject *object, GAsyncResult *result, gpointer user_data)
static void fake_message_cb(FlBinaryMessenger *messenger, const gchar *channel, GBytes *message, FlBinaryMessengerResponseHandle *response_handle, gpointer user_data)
static void kill_handler_notify_cb(gpointer was_called)
static gboolean quit_main_loop_cb(gpointer user_data)
static void fl_fake_binary_messenger_iface_init(FlBinaryMessengerInterface *iface)
G_DECLARE_FINAL_TYPE(FlFakeBinaryMessenger, fl_fake_binary_messenger, FL, FAKE_BINARY_MESSENGER, GObject) struct _FlFakeBinaryMessenger
static void fake_response_cb(GObject *object, GAsyncResult *result, gpointer user_data)
static void failure_response_cb(GObject *object, GAsyncResult *result, gpointer user_data)
static void response_from_thread_cb(FlBinaryMessenger *messenger, const gchar *channel, GBytes *message, FlBinaryMessengerResponseHandle *response_handle, gpointer user_data)
static void echo_response_cb(GObject *object, GAsyncResult *result, gpointer user_data)
static GBytes * send_on_channel_finish(FlBinaryMessenger *messenger, GAsyncResult *result, GError **error)
static FlBinaryMessenger * fl_fake_binary_messenger_new(GMainLoop *loop)
FlutterEngineProcTable * fl_engine_get_embedder_api(FlEngine *self)
gboolean fl_engine_start(FlEngine *self, GError **error)
static FlEngine * make_mock_engine()
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
const uint8_t uint32_t uint32_t GError ** error
FlMockBinaryMessengerResponseHandle * fl_mock_binary_messenger_response_handle_new()
void * malloc(size_t size)
void ResizeChannel(BinaryMessenger *messenger, std::string name, int new_size)
#define MOCK_ENGINE_PROC(proc, mock_impl)
Function-pointer-based versions of the APIs above.
FlutterEngineSendPlatformMessageFnPtr SendPlatformMessage
FlBinaryMessenger * messenger
FlBinaryMessengerResponseHandle * response_handle
#define EXPECT_TRUE(handle)