| Flutter Linux Embedder |

fl_binary_messenger_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 // Included first as it collides with the X11 headers.
6 #include "gtest/gtest.h"
7
8 #include <pthread.h>
9 #include <cstring>
10
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"
21
22 G_DECLARE_FINAL_TYPE(FlFakeBinaryMessenger,
23 fl_fake_binary_messenger,
24 FL,
25 FAKE_BINARY_MESSENGER,
26 GObject)
27
28 struct _FlFakeBinaryMessenger {
29 GObject parent_instance;
30
31 GMainLoop* loop;
32 GAsyncReadyCallback send_callback;
33 gpointer send_callback_user_data;
34 FlBinaryMessengerMessageHandler message_handler;
35 gpointer message_handler_user_data;
36 };
37
38 static void fl_fake_binary_messenger_iface_init(
39 FlBinaryMessengerInterface* iface);
40
41 G_DEFINE_TYPE_WITH_CODE(
42 FlFakeBinaryMessenger,
43 fl_fake_binary_messenger,
44 G_TYPE_OBJECT,
45 G_IMPLEMENT_INTERFACE(fl_binary_messenger_get_type(),
46 fl_fake_binary_messenger_iface_init))
47
48 static void fl_fake_binary_messenger_class_init(
49 FlFakeBinaryMessengerClass* klass) {}
50
51 static gboolean send_message_cb(gpointer user_data) {
52 FlFakeBinaryMessenger* self = FL_FAKE_BINARY_MESSENGER(user_data);
53
54 const char* text = "Marco!";
55 g_autoptr(GBytes) message = g_bytes_new(text, strlen(text));
56 self->message_handler(FL_BINARY_MESSENGER(self), "CHANNEL", message,
57 FL_BINARY_MESSENGER_RESPONSE_HANDLE(
58 fl_mock_binary_messenger_response_handle_new()),
59 self->message_handler_user_data);
60
61 return FALSE;
62 }
63
64 static void set_message_handler_on_channel(
65 FlBinaryMessenger* messenger,
66 const gchar* channel,
67 FlBinaryMessengerMessageHandler handler,
68 gpointer user_data,
69 GDestroyNotify destroy_notify) {
70 FlFakeBinaryMessenger* self = FL_FAKE_BINARY_MESSENGER(messenger);
71
72 EXPECT_STREQ(channel, "CHANNEL");
73
74 // Send message.
75 self->message_handler = handler;
76 self->message_handler_user_data = user_data;
77 g_idle_add(send_message_cb, messenger);
78 }
79
80 static gboolean send_response(FlBinaryMessenger* messenger,
81 FlBinaryMessengerResponseHandle* response_handle,
82 GBytes* response,
83 GError** error) {
84 FlFakeBinaryMessenger* self = FL_FAKE_BINARY_MESSENGER(messenger);
85
86 EXPECT_TRUE(FL_IS_MOCK_BINARY_MESSENGER_RESPONSE_HANDLE(response_handle));
87
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!");
92
93 g_main_loop_quit(self->loop);
94
95 return TRUE;
96 }
97
98 static gboolean send_ready_cb(gpointer user_data) {
99 FlFakeBinaryMessenger* self = FL_FAKE_BINARY_MESSENGER(user_data);
100
101 self->send_callback(G_OBJECT(self), NULL, self->send_callback_user_data);
102
103 return FALSE;
104 }
105
106 static void send_on_channel(FlBinaryMessenger* messenger,
107 const gchar* channel,
108 GBytes* message,
109 GCancellable* cancellable,
110 GAsyncReadyCallback callback,
111 gpointer user_data) {
112 FlFakeBinaryMessenger* self = FL_FAKE_BINARY_MESSENGER(messenger);
113
114 EXPECT_STREQ(channel, "CHANNEL");
115 g_autofree gchar* text =
116 g_strndup(static_cast<const gchar*>(g_bytes_get_data(message, nullptr)),
117 g_bytes_get_size(message));
118 EXPECT_STREQ(text, "Marco!");
119
120 // Send response.
121 self->send_callback = callback;
122 self->send_callback_user_data = user_data;
123 g_idle_add(send_ready_cb, messenger);
124 }
125
126 static GBytes* send_on_channel_finish(FlBinaryMessenger* messenger,
127 GAsyncResult* result,
128 GError** error) {
129 const char* text = "Polo!";
130 return g_bytes_new(text, strlen(text));
131 }
132
133 static void resize_channel(FlBinaryMessenger* messenger,
134 const gchar* channel,
135 int64_t new_size) {
136 // Fake implementation. Do nothing.
137 }
138
139 static void set_warns_on_channel_overflow(FlBinaryMessenger* messenger,
140 const gchar* channel,
141 bool warns) {
142 // Fake implementation. Do nothing.
143 }
144
145 static void fl_fake_binary_messenger_iface_init(
146 FlBinaryMessengerInterface* iface) {
147 iface->set_message_handler_on_channel = set_message_handler_on_channel;
148 iface->send_response = send_response;
149 iface->send_on_channel = send_on_channel;
150 iface->send_on_channel_finish = send_on_channel_finish;
151 iface->resize_channel = resize_channel;
152 iface->set_warns_on_channel_overflow = set_warns_on_channel_overflow;
153 }
154
155 static void fl_fake_binary_messenger_init(FlFakeBinaryMessenger* self) {}
156
157 static FlBinaryMessenger* fl_fake_binary_messenger_new(GMainLoop* loop) {
158 FlFakeBinaryMessenger* self = FL_FAKE_BINARY_MESSENGER(
159 g_object_new(fl_fake_binary_messenger_get_type(), NULL));
160 self->loop = loop;
161 return FL_BINARY_MESSENGER(self);
162 }
163
164 // Called when the message response is received in the FakeMessengerSend test.
165 static void fake_response_cb(GObject* object,
166 GAsyncResult* result,
167 gpointer user_data) {
168 g_autoptr(GError) error = nullptr;
169 g_autoptr(GBytes) message = fl_binary_messenger_send_on_channel_finish(
170 FL_BINARY_MESSENGER(object), result, &error);
171 EXPECT_NE(message, nullptr);
172 EXPECT_EQ(error, nullptr);
173
174 g_autofree gchar* text =
175 g_strndup(static_cast<const gchar*>(g_bytes_get_data(message, nullptr)),
176 g_bytes_get_size(message));
177 EXPECT_STREQ(text, "Polo!");
178
179 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
180 }
181
182 // Checks can make a fake messenger and send a message.
183 TEST(FlBinaryMessengerTest, FakeMessengerSend) {
184 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
185
186 g_autoptr(FlBinaryMessenger) messenger = fl_fake_binary_messenger_new(loop);
187 EXPECT_TRUE(FL_IS_FAKE_BINARY_MESSENGER(messenger));
188
189 const char* text = "Marco!";
190 g_autoptr(GBytes) message = g_bytes_new(text, strlen(text));
191 fl_binary_messenger_send_on_channel(messenger, "CHANNEL", message, nullptr,
192 fake_response_cb, loop);
193
194 // Blocks here until fake_response_cb is called.
195 g_main_loop_run(loop);
196 }
197
198 // Called when a message is received in the FakeMessengerReceive test.
199 static void fake_message_cb(FlBinaryMessenger* messenger,
200 const gchar* channel,
201 GBytes* message,
202 FlBinaryMessengerResponseHandle* response_handle,
203 gpointer user_data) {
204 EXPECT_STREQ(channel, "CHANNEL");
205
206 EXPECT_NE(message, nullptr);
207 g_autofree gchar* text =
208 g_strndup(static_cast<const gchar*>(g_bytes_get_data(message, nullptr)),
209 g_bytes_get_size(message));
210 EXPECT_STREQ(text, "Marco!");
211
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;
216 EXPECT_TRUE(fl_binary_messenger_send_response(messenger, response_handle,
217 response, &error));
218 EXPECT_EQ(error, nullptr);
219 }
220
221 // Checks can make a fake messenger and receive a message.
222 TEST(FlBinaryMessengerTest, FakeMessengerReceive) {
223 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
224
225 g_autoptr(FlBinaryMessenger) messenger = fl_fake_binary_messenger_new(loop);
226 EXPECT_TRUE(FL_IS_FAKE_BINARY_MESSENGER(messenger));
227
228 fl_binary_messenger_set_message_handler_on_channel(
229 messenger, "CHANNEL", fake_message_cb, nullptr, nullptr);
230
231 // Blocks here until response is received in fake messenger.
232 g_main_loop_run(loop);
233 }
234
235 // Checks sending nullptr for a message works.
236 TEST(FlBinaryMessengerTest, SendNullptrMessage) {
237 g_autoptr(FlEngine) engine = make_mock_engine();
238 FlBinaryMessenger* messenger = fl_binary_messenger_new(engine);
239 fl_binary_messenger_send_on_channel(messenger, "test/echo", nullptr, nullptr,
240 nullptr, nullptr);
241 }
242
243 // Checks sending a zero length message works.
244 TEST(FlBinaryMessengerTest, SendEmptyMessage) {
245 g_autoptr(FlEngine) engine = make_mock_engine();
246 FlBinaryMessenger* messenger = fl_binary_messenger_new(engine);
247 g_autoptr(GBytes) message = g_bytes_new(nullptr, 0);
248 fl_binary_messenger_send_on_channel(messenger, "test/echo", message, nullptr,
249 nullptr, nullptr);
250 }
251
252 // Called when the message response is received in the SendMessage test.
253 static void echo_response_cb(GObject* object,
254 GAsyncResult* result,
255 gpointer user_data) {
256 g_autoptr(GError) error = nullptr;
257 g_autoptr(GBytes) message = fl_binary_messenger_send_on_channel_finish(
258 FL_BINARY_MESSENGER(object), result, &error);
259 EXPECT_NE(message, nullptr);
260 EXPECT_EQ(error, nullptr);
261
262 g_autofree gchar* text =
263 g_strndup(static_cast<const gchar*>(g_bytes_get_data(message, nullptr)),
264 g_bytes_get_size(message));
265 EXPECT_STREQ(text, "Hello World!");
266
267 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
268 }
269
270 // Checks sending a message works.
271 TEST(FlBinaryMessengerTest, SendMessage) {
272 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
273
274 g_autoptr(FlEngine) engine = make_mock_engine();
275 FlBinaryMessenger* messenger = fl_binary_messenger_new(engine);
276 const char* text = "Hello World!";
277 g_autoptr(GBytes) message = g_bytes_new(text, strlen(text));
278 fl_binary_messenger_send_on_channel(messenger, "test/echo", message, nullptr,
279 echo_response_cb, loop);
280
281 // Blocks here until echo_response_cb is called.
282 g_main_loop_run(loop);
283 }
284
285 // Called when the message response is received in the NullptrResponse test.
286 static void nullptr_response_cb(GObject* object,
287 GAsyncResult* result,
288 gpointer user_data) {
289 g_autoptr(GError) error = nullptr;
290 g_autoptr(GBytes) message = fl_binary_messenger_send_on_channel_finish(
291 FL_BINARY_MESSENGER(object), result, &error);
292 EXPECT_NE(message, nullptr);
293 EXPECT_EQ(error, nullptr);
294
295 EXPECT_EQ(g_bytes_get_size(message), static_cast<gsize>(0));
296
297 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
298 }
299
300 // Checks the engine returning a nullptr message work.
301 TEST(FlBinaryMessengerTest, NullptrResponse) {
302 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
303
304 g_autoptr(FlEngine) engine = make_mock_engine();
305 FlBinaryMessenger* messenger = fl_binary_messenger_new(engine);
306 const char* text = "Hello World!";
307 g_autoptr(GBytes) message = g_bytes_new(text, strlen(text));
308 fl_binary_messenger_send_on_channel(messenger, "test/nullptr-response",
309 message, nullptr, nullptr_response_cb,
310 loop);
311
312 // Blocks here until nullptr_response_cb is called.
313 g_main_loop_run(loop);
314 }
315
316 // Called when the message response is received in the SendFailure test.
317 static void failure_response_cb(GObject* object,
318 GAsyncResult* result,
319 gpointer user_data) {
320 g_autoptr(GError) error = nullptr;
321 g_autoptr(GBytes) message = fl_binary_messenger_send_on_channel_finish(
322 FL_BINARY_MESSENGER(object), result, &error);
323 EXPECT_EQ(message, nullptr);
324 EXPECT_NE(error, nullptr);
325
326 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
327 }
328
329 // Checks the engine reporting a send failure is handled.
330 TEST(FlBinaryMessengerTest, SendFailure) {
331 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
332
333 g_autoptr(FlEngine) engine = make_mock_engine();
334 FlBinaryMessenger* messenger = fl_binary_messenger_new(engine);
335 fl_binary_messenger_send_on_channel(messenger, "test/failure", nullptr,
336 nullptr, failure_response_cb, loop);
337
338 // Blocks here until failure_response_cb is called.
339 g_main_loop_run(loop);
340 }
341
342 // Called when a message is received from the engine in the ReceiveMessage test.
343 static void message_cb(FlBinaryMessenger* messenger,
344 const gchar* channel,
345 GBytes* message,
346 FlBinaryMessengerResponseHandle* response_handle,
347 gpointer user_data) {
348 EXPECT_NE(message, nullptr);
349 g_autofree gchar* text =
350 g_strndup(static_cast<const gchar*>(g_bytes_get_data(message, nullptr)),
351 g_bytes_get_size(message));
352 EXPECT_STREQ(text, "Marco!");
353
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;
358 EXPECT_TRUE(fl_binary_messenger_send_response(messenger, response_handle,
359 response, &error));
360 EXPECT_EQ(error, nullptr);
361 }
362
363 // Called when a the test engine notifies us what response we sent in the
364 // ReceiveMessage test.
365 static void response_cb(FlBinaryMessenger* messenger,
366 const gchar* channel,
367 GBytes* message,
368 FlBinaryMessengerResponseHandle* response_handle,
369 gpointer user_data) {
370 EXPECT_NE(message, nullptr);
371 g_autofree gchar* text =
372 g_strndup(static_cast<const gchar*>(g_bytes_get_data(message, nullptr)),
373 g_bytes_get_size(message));
374 EXPECT_STREQ(text, "Polo!");
375
376 fl_binary_messenger_send_response(messenger, response_handle, nullptr,
377 nullptr);
378
379 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
380 }
381
382 // Checks the shell able to receive and respond to messages from the engine.
383 TEST(FlBinaryMessengerTest, ReceiveMessage) {
384 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
385
386 g_autoptr(FlEngine) engine = make_mock_engine();
387 FlBinaryMessenger* messenger = fl_binary_messenger_new(engine);
388
389 // Listen for messages from the engine.
390 fl_binary_messenger_set_message_handler_on_channel(
391 messenger, "test/messages", message_cb, nullptr, nullptr);
392
393 // Listen for response from the engine.
394 fl_binary_messenger_set_message_handler_on_channel(
395 messenger, "test/responses", response_cb, loop, nullptr);
396
397 // Trigger the engine to send a message.
398 const char* text = "Marco!";
399 g_autoptr(GBytes) message = g_bytes_new(text, strlen(text));
400 fl_binary_messenger_send_on_channel(messenger, "test/send-message", message,
401 nullptr, nullptr, nullptr);
402
403 // Blocks here until response_cb is called.
404 g_main_loop_run(loop);
405 }
406
407 // MOCK_ENGINE_PROC is leaky by design.
408 // NOLINTBEGIN(clang-analyzer-core.StackAddressEscape)
409
410 // Checks if the 'resize' command is sent and is well-formed.
411 TEST(FlBinaryMessengerTest, ResizeChannel) {
412 g_autoptr(FlEngine) engine = make_mock_engine();
413 FlutterEngineProcTable* embedder_api = fl_engine_get_embedder_api(engine);
414
415 bool called = false;
416
417 FlutterEngineSendPlatformMessageFnPtr old_handler =
418 embedder_api->SendPlatformMessage;
419 embedder_api->SendPlatformMessage = MOCK_ENGINE_PROC(
420 SendPlatformMessage,
421 ([&called, old_handler](auto engine,
422 const FlutterPlatformMessage* message) {
423 // Expect to receive a message on the "control" channel.
424 if (strcmp(message->channel, "dev.flutter/channel-buffers") != 0) {
425 return old_handler(engine, message);
426 }
427
428 called = true;
429
430 // The expected content was created from the following Dart code:
431 // MethodCall call = MethodCall('resize', ['flutter/test',3]);
432 // StandardMethodCodec().encodeMethodCall(call).buffer.asUint8List();
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]);
442 }
443
444 return kSuccess;
445 }));
446
447 g_autoptr(GError) error = nullptr;
448 EXPECT_TRUE(fl_engine_start(engine, &error));
449 EXPECT_EQ(error, nullptr);
450
451 FlBinaryMessenger* messenger = fl_binary_messenger_new(engine);
452 fl_binary_messenger_resize_channel(messenger, "flutter/test", 3);
453
454 EXPECT_TRUE(called);
455 }
456
457 // Checks if the 'overflow' command is sent and is well-formed.
458 TEST(FlBinaryMessengerTest, WarnsOnOverflowChannel) {
459 g_autoptr(FlEngine) engine = make_mock_engine();
460 FlutterEngineProcTable* embedder_api = fl_engine_get_embedder_api(engine);
461
462 bool called = false;
463
464 FlutterEngineSendPlatformMessageFnPtr old_handler =
465 embedder_api->SendPlatformMessage;
466 embedder_api->SendPlatformMessage = MOCK_ENGINE_PROC(
467 SendPlatformMessage,
468 ([&called, old_handler](auto engine,
469 const FlutterPlatformMessage* message) {
470 // Expect to receive a message on the "control" channel.
471 if (strcmp(message->channel, "dev.flutter/channel-buffers") != 0) {
472 return old_handler(engine, message);
473 }
474
475 called = true;
476
477 // The expected content was created from the following Dart code:
478 // MethodCall call = MethodCall('overflow',['flutter/test', true]);
479 // StandardMethodCodec().encodeMethodCall(call).buffer.asUint8List();
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]);
488 }
489
490 return kSuccess;
491 }));
492
493 g_autoptr(GError) error = nullptr;
494 EXPECT_TRUE(fl_engine_start(engine, &error));
495 EXPECT_EQ(error, nullptr);
496
497 FlBinaryMessenger* messenger = fl_binary_messenger_new(engine);
498 fl_binary_messenger_set_warns_on_channel_overflow(messenger, "flutter/test",
499 false);
500
501 EXPECT_TRUE(called);
502 }
503
504 static gboolean quit_main_loop_cb(gpointer user_data) {
505 g_main_loop_quit(static_cast<GMainLoop*>(user_data));
506 return FALSE;
507 }
508
509 // Checks if error returned when invoking a command on the control channel
510 // are handled.
511 TEST(FlBinaryMessengerTest, ControlChannelErrorResponse) {
512 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
513 g_autoptr(FlEngine) engine = make_mock_engine();
514 FlBinaryMessenger* messenger = fl_binary_messenger_new(engine);
515
516 g_autoptr(GError) error = nullptr;
517 EXPECT_TRUE(fl_engine_start(engine, &error));
518 EXPECT_EQ(error, nullptr);
519
520 FlutterEngineProcTable* embedder_api = fl_engine_get_embedder_api(engine);
521
522 bool called = false;
523
524 FlutterEngineSendPlatformMessageFnPtr old_handler =
525 embedder_api->SendPlatformMessage;
526 embedder_api->SendPlatformMessage = MOCK_ENGINE_PROC(
527 SendPlatformMessage,
528 ([&called, old_handler, loop](auto engine,
529 const FlutterPlatformMessage* message) {
530 // Expect to receive a message on the "control" channel.
531 if (strcmp(message->channel, "dev.flutter/channel-buffers") != 0) {
532 return old_handler(engine, message);
533 }
534
535 called = true;
536
537 // Register a callback to quit the main loop when binary messenger work
538 // ends.
539 g_idle_add(quit_main_loop_cb, loop);
540
541 // Simulates an internal error.
542 return kInvalidArguments;
543 }));
544
545 fl_binary_messenger_set_warns_on_channel_overflow(messenger, "flutter/test",
546 false);
547
548 EXPECT_TRUE(called);
549
550 // Blocks here until quit_main_loop_cb is called.
551 g_main_loop_run(loop);
552 }
553
554 // NOLINTEND(clang-analyzer-core.StackAddressEscape)
555
556 struct RespondsOnBackgroundThreadInfo {
557 FlBinaryMessenger* messenger;
558 FlBinaryMessengerResponseHandle* response_handle;
559 GMainLoop* loop;
560 };
561
562 static gboolean cleanup_responds_on_background_thread_info(gpointer user_data) {
563 RespondsOnBackgroundThreadInfo* info =
564 static_cast<RespondsOnBackgroundThreadInfo*>(user_data);
565 GMainLoop* loop = info->loop;
566
567 g_object_unref(info->messenger);
568 g_object_unref(info->response_handle);
569 free(info);
570
571 g_main_loop_quit(static_cast<GMainLoop*>(loop));
572
573 return G_SOURCE_REMOVE;
574 }
575
576 static void* response_from_thread_main(void* user_data) {
577 RespondsOnBackgroundThreadInfo* info =
578 static_cast<RespondsOnBackgroundThreadInfo*>(user_data);
579
580 fl_binary_messenger_send_response(info->messenger, info->response_handle,
581 nullptr, nullptr);
582
583 g_idle_add(cleanup_responds_on_background_thread_info, info);
584
585 return nullptr;
586 }
587
588 static void response_from_thread_cb(
589 FlBinaryMessenger* messenger,
590 const gchar* channel,
591 GBytes* message,
592 FlBinaryMessengerResponseHandle* response_handle,
593 gpointer user_data) {
594 EXPECT_NE(message, nullptr);
595 pthread_t thread;
596 RespondsOnBackgroundThreadInfo* info =
597 static_cast<RespondsOnBackgroundThreadInfo*>(
598 malloc(sizeof(RespondsOnBackgroundThreadInfo)));
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));
602 info->loop = static_cast<GMainLoop*>(user_data);
603 EXPECT_EQ(0,
604 pthread_create(&thread, nullptr, &response_from_thread_main, info));
605 }
606
607 TEST(FlBinaryMessengerTest, RespondOnBackgroundThread) {
608 g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0);
609
610 g_autoptr(FlEngine) engine = make_mock_engine();
611 FlBinaryMessenger* messenger = fl_binary_messenger_new(engine);
612
613 // Listen for messages from the engine.
614 fl_binary_messenger_set_message_handler_on_channel(
615 messenger, "test/messages", message_cb, nullptr, nullptr);
616
617 // Listen for response from the engine.
618 fl_binary_messenger_set_message_handler_on_channel(
619 messenger, "test/responses", response_from_thread_cb, loop, nullptr);
620
621 // Trigger the engine to send a message.
622 const char* text = "Marco!";
623 g_autoptr(GBytes) message = g_bytes_new(text, strlen(text));
624 fl_binary_messenger_send_on_channel(messenger, "test/send-message", message,
625 nullptr, nullptr, nullptr);
626
627 // Blocks here until response_cb is called.
628 g_main_loop_run(loop);
629 }
630
631 static void kill_handler_notify_cb(gpointer was_called) {
632 *static_cast<gboolean*>(was_called) = TRUE;
633 }
634
635 TEST(FlBinaryMessengerTest, DeletingEngineClearsHandlers) {
636 FlEngine* engine = make_mock_engine();
637 g_autoptr(FlBinaryMessenger) messenger = fl_binary_messenger_new(engine);
638 gboolean was_killed = FALSE;
639
640 // Listen for messages from the engine.
641 fl_binary_messenger_set_message_handler_on_channel(messenger, "test/messages",
642 message_cb, &was_killed,
643 kill_handler_notify_cb);
644
645 g_clear_object(&engine);
646
647 ASSERT_TRUE(was_killed);
648 }
G_DECLARE_FINAL_TYPE
G_DECLARE_FINAL_TYPE(FlFakeBinaryMessenger, fl_fake_binary_messenger, FL, FAKE_BINARY_MESSENGER, GObject) struct _FlFakeBinaryMessenger
Definition: fl_binary_messenger_test.cc:22
G_DEFINE_TYPE_WITH_CODE
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)
Definition: fl_binary_messenger_test.cc:41
response_from_thread_cb
static void response_from_thread_cb(FlBinaryMessenger *messenger, const gchar *channel, GBytes *message, FlBinaryMessengerResponseHandle *response_handle, gpointer user_data)
Definition: fl_binary_messenger_test.cc:588
fl_engine_get_embedder_api
FlutterEngineProcTable * fl_engine_get_embedder_api(FlEngine *self)
Definition: fl_engine.cc:591
send_ready_cb
static gboolean send_ready_cb(gpointer user_data)
Definition: fl_binary_messenger_test.cc:98
kill_handler_notify_cb
static void kill_handler_notify_cb(gpointer was_called)
Definition: fl_binary_messenger_test.cc:631
RespondsOnBackgroundThreadInfo::messenger
FlBinaryMessenger * messenger
Definition: fl_binary_messenger_test.cc:557
echo_response_cb
static void echo_response_cb(GObject *object, GAsyncResult *result, gpointer user_data)
Definition: fl_binary_messenger_test.cc:253
fl_fake_binary_messenger_new
static FlBinaryMessenger * fl_fake_binary_messenger_new(GMainLoop *loop)
Definition: fl_binary_messenger_test.cc:157
fl_method_channel.h
cleanup_responds_on_background_thread_info
static gboolean cleanup_responds_on_background_thread_info(gpointer user_data)
Definition: fl_binary_messenger_test.cc:562
response_cb
static void response_cb(FlBinaryMessenger *messenger, const gchar *channel, GBytes *message, FlBinaryMessengerResponseHandle *response_handle, gpointer user_data)
Definition: fl_binary_messenger_test.cc:365
user_data
FlKeyEvent uint64_t FlKeyResponderAsyncCallback gpointer user_data
Definition: fl_key_channel_responder.cc:121
set_warns_on_channel_overflow
static void set_warns_on_channel_overflow(FlBinaryMessenger *messenger, const gchar *channel, bool warns)
Definition: fl_binary_messenger_test.cc:139
fl_binary_messenger_new
FlBinaryMessenger * fl_binary_messenger_new(FlEngine *engine)
Definition: fl_binary_messenger.cc:406
quit_main_loop_cb
static gboolean quit_main_loop_cb(gpointer user_data)
Definition: fl_binary_messenger_test.cc:504
make_mock_engine
static FlEngine * make_mock_engine()
Definition: fl_event_channel_test.cc:24
response_from_thread_main
static void * response_from_thread_main(void *user_data)
Definition: fl_binary_messenger_test.cc:576
nullptr_response_cb
static void nullptr_response_cb(GObject *object, GAsyncResult *result, gpointer user_data)
Definition: fl_binary_messenger_test.cc:286
send_response
static gboolean send_response(FlBinaryMessenger *messenger, FlBinaryMessengerResponseHandle *response_handle, GBytes *response, GError **error)
Definition: fl_binary_messenger_test.cc:80
RespondsOnBackgroundThreadInfo
Definition: fl_binary_messenger_test.cc:556
fl_binary_messenger_set_warns_on_channel_overflow
G_MODULE_EXPORT void fl_binary_messenger_set_warns_on_channel_overflow(FlBinaryMessenger *self, const gchar *channel, bool warns)
Definition: fl_binary_messenger.cc:484
fl_binary_messenger.h
send_on_channel
static void send_on_channel(FlBinaryMessenger *messenger, const gchar *channel, GBytes *message, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
Definition: fl_binary_messenger_test.cc:106
fake_response_cb
static void fake_response_cb(GObject *object, GAsyncResult *result, gpointer user_data)
Definition: fl_binary_messenger_test.cc:165
flutter::internal::ResizeChannel
void ResizeChannel(BinaryMessenger *messenger, std::string name, int new_size)
Definition: core_implementations.cc:181
fl_engine_private.h
fl_binary_messenger_set_message_handler_on_channel
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)
Definition: fl_binary_messenger.cc:424
TRUE
return TRUE
Definition: fl_pixel_buffer_texture_test.cc:53
FlBinaryMessengerMessageHandler
G_MODULE_EXPORT GObject typedef void(* FlBinaryMessengerMessageHandler)(FlBinaryMessenger *messenger, const gchar *channel, GBytes *message, FlBinaryMessengerResponseHandle *response_handle, gpointer user_data)
Definition: fl_binary_messenger.h:66
RespondsOnBackgroundThreadInfo::response_handle
FlBinaryMessengerResponseHandle * response_handle
Definition: fl_binary_messenger_test.cc:558
fl_binary_messenger_send_on_channel_finish
G_MODULE_EXPORT GBytes * fl_binary_messenger_send_on_channel_finish(FlBinaryMessenger *self, GAsyncResult *result, GError **error)
Definition: fl_binary_messenger.cc:465
FL
FL
Definition: fl_binary_messenger.cc:27
failure_response_cb
static void failure_response_cb(GObject *object, GAsyncResult *result, gpointer user_data)
Definition: fl_binary_messenger_test.cc:317
fl_standard_method_codec.h
self
GdkEvent FlView * self
Definition: fl_view.cc:100
fl_binary_messenger_private.h
result
GAsyncResult * result
Definition: fl_text_input_plugin.cc:106
error
const uint8_t uint32_t uint32_t GError ** error
Definition: fl_pixel_buffer_texture_test.cc:40
fl_fake_binary_messenger_iface_init
static void fl_fake_binary_messenger_iface_init(FlBinaryMessengerInterface *iface)
Definition: fl_binary_messenger_test.cc:145
message_cb
static void message_cb(FlBinaryMessenger *messenger, const gchar *channel, GBytes *message, FlBinaryMessengerResponseHandle *response_handle, gpointer user_data)
Definition: fl_binary_messenger_test.cc:343
RespondsOnBackgroundThreadInfo::loop
GMainLoop * loop
Definition: fl_binary_messenger_test.cc:559
set_message_handler_on_channel
static void set_message_handler_on_channel(FlBinaryMessenger *messenger, const gchar *channel, FlBinaryMessengerMessageHandler handler, gpointer user_data, GDestroyNotify destroy_notify)
Definition: fl_binary_messenger_test.cc:64
fl_engine_start
gboolean fl_engine_start(FlEngine *self, GError **error)
Definition: fl_engine.cc:483
fake_message_cb
static void fake_message_cb(FlBinaryMessenger *messenger, const gchar *channel, GBytes *message, FlBinaryMessengerResponseHandle *response_handle, gpointer user_data)
Definition: fl_binary_messenger_test.cc:199
resize_channel
static void resize_channel(FlBinaryMessenger *messenger, const gchar *channel, int64_t new_size)
Definition: fl_binary_messenger_test.cc:133
engine
FlEngine * engine
Definition: fl_view_accessible.cc:29
callback
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
Definition: fl_key_channel_responder.cc:120
fl_binary_messenger_resize_channel
G_MODULE_EXPORT void fl_binary_messenger_resize_channel(FlBinaryMessenger *self, const gchar *channel, int64_t new_size)
Definition: fl_binary_messenger.cc:475
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:438
TEST
TEST(FlBinaryMessengerTest, FakeMessengerSend)
Definition: fl_binary_messenger_test.cc:183
fl_fake_binary_messenger_init
static void fl_fake_binary_messenger_init(FlFakeBinaryMessenger *self)
Definition: fl_binary_messenger_test.cc:155
send_message_cb
static gboolean send_message_cb(gpointer user_data)
Definition: fl_binary_messenger_test.cc:51
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:451
send_on_channel_finish
static GBytes * send_on_channel_finish(FlBinaryMessenger *messenger, GAsyncResult *result, GError **error)
Definition: fl_binary_messenger_test.cc:126