Flutter Linux Embedder
fl_method_channel_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 "flutter/shell/platform/linux/testing/linux_test.h"
7 #include "gtest/gtest.h"
8 
12 #include "flutter/shell/platform/linux/testing/fl_mock_binary_messenger.h"
13 
14 class FlMethodChannelTest : public flutter::testing::LinuxTest {
15  protected:
16  void SetUp() override { messenger = fl_mock_binary_messenger_new(); }
17 
18  ~FlMethodChannelTest() { g_clear_object(&messenger); }
19 
20  FlMockBinaryMessenger* messenger = nullptr;
21 };
22 
23 // Checks if invoking a method returns a value.
24 TEST_F(FlMethodChannelTest, InvokeMethod) {
25  fl_mock_binary_messenger_set_standard_method_channel(
26  messenger, "test",
27  [](FlMockBinaryMessenger* messenger, GTask* task, const gchar* name,
28  FlValue* args, gpointer user_data) {
29  EXPECT_STREQ(name, "Test");
31  EXPECT_STREQ(fl_value_get_string(args), "Marco!");
32  g_autoptr(FlValue) return_value = fl_value_new_string("Polo!");
33  return FL_METHOD_RESPONSE(fl_method_success_response_new(return_value));
34  },
35  nullptr);
36 
37  g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
38  g_autoptr(FlMethodChannel) channel = fl_method_channel_new(
39  FL_BINARY_MESSENGER(messenger), "test", FL_METHOD_CODEC(codec));
40 
43  channel, "Test", args, nullptr,
44  [](GObject* object, GAsyncResult* result, gpointer user_data) {
45  g_autoptr(GError) error = nullptr;
46  g_autoptr(FlMethodResponse) response =
47  fl_method_channel_invoke_method_finish(FL_METHOD_CHANNEL(object),
48  result, &error);
49  EXPECT_NE(response, nullptr);
50  EXPECT_EQ(error, nullptr);
51 
53  EXPECT_NE(r, nullptr);
54  EXPECT_EQ(error, nullptr);
55 
57  EXPECT_STREQ(fl_value_get_string(r), "Polo!");
58 
59  g_main_loop_quit(static_cast<GMainLoop*>(user_data));
60  },
61  loop);
62 
63  g_main_loop_run(loop);
64 }
65 
66 // Checks if a method can be invoked with nullptr for arguments.
67 TEST_F(FlMethodChannelTest, InvokeMethodNullptrArgsMessage) {
68  fl_mock_binary_messenger_set_standard_method_channel(
69  messenger, "test",
70  [](FlMockBinaryMessenger* messenger, GTask* task, const gchar* name,
71  FlValue* args, gpointer user_data) {
72  EXPECT_STREQ(name, "Test");
74  return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
75  },
76  nullptr);
77 
78  g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
79  g_autoptr(FlMethodChannel) channel = fl_method_channel_new(
80  FL_BINARY_MESSENGER(messenger), "test", FL_METHOD_CODEC(codec));
81 
83  channel, "Test", nullptr, nullptr,
84  [](GObject* object, GAsyncResult* result, gpointer user_data) {
85  g_autoptr(GError) error = nullptr;
86  g_autoptr(FlMethodResponse) response =
87  fl_method_channel_invoke_method_finish(FL_METHOD_CHANNEL(object),
88  result, &error);
89  EXPECT_NE(response, nullptr);
90  EXPECT_EQ(error, nullptr);
91 
93  EXPECT_NE(r, nullptr);
94  EXPECT_EQ(error, nullptr);
96 
97  g_main_loop_quit(static_cast<GMainLoop*>(user_data));
98  },
99  loop);
100 
101  g_main_loop_run(loop);
102 }
103 
104 // Checks if an error response from a method call is handled.
105 TEST_F(FlMethodChannelTest, InvokeMethodError) {
106  fl_mock_binary_messenger_set_standard_method_channel(
107  messenger, "test",
108  [](FlMockBinaryMessenger* messenger, GTask* task, const gchar* name,
109  FlValue* args, gpointer user_data) {
110  EXPECT_STREQ(name, "Test");
111  g_autoptr(FlValue) details = fl_value_new_string("DETAILS");
112  return FL_METHOD_RESPONSE(
113  fl_method_error_response_new("CODE", "MESSAGE", details));
114  },
115  nullptr);
116 
117  g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
118  g_autoptr(FlMethodChannel) channel = fl_method_channel_new(
119  FL_BINARY_MESSENGER(messenger), "test", FL_METHOD_CODEC(codec));
120 
122  channel, "Test", nullptr, nullptr,
123  [](GObject* object, GAsyncResult* result, gpointer user_data) {
124  g_autoptr(GError) error = nullptr;
125  g_autoptr(FlMethodResponse) response =
126  fl_method_channel_invoke_method_finish(FL_METHOD_CHANNEL(object),
127  result, &error);
128  EXPECT_NE(response, nullptr);
129  EXPECT_EQ(error, nullptr);
130 
131  EXPECT_TRUE(FL_IS_METHOD_ERROR_RESPONSE(response));
133  FL_METHOD_ERROR_RESPONSE(response)),
134  "CODE");
136  FL_METHOD_ERROR_RESPONSE(response)),
137  "MESSAGE");
139  FL_METHOD_ERROR_RESPONSE(response));
140  EXPECT_NE(details, nullptr);
141  EXPECT_EQ(fl_value_get_type(details), FL_VALUE_TYPE_STRING);
142  EXPECT_STREQ(fl_value_get_string(details), "DETAILS");
143 
144  g_main_loop_quit(static_cast<GMainLoop*>(user_data));
145  },
146  loop);
147 
148  g_main_loop_run(loop);
149 }
150 
151 // Checks if a not implemeneted response from a method call is handled.
152 TEST_F(FlMethodChannelTest, InvokeMethodNotImplemented) {
153  fl_mock_binary_messenger_set_standard_method_channel(
154  messenger, "test",
155  [](FlMockBinaryMessenger* messenger, GTask* task, const gchar* name,
156  FlValue* args, gpointer user_data) {
157  EXPECT_STREQ(name, "Test");
158  return FL_METHOD_RESPONSE(fl_method_not_implemented_response_new());
159  },
160  nullptr);
161 
162  g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
163  g_autoptr(FlMethodChannel) channel = fl_method_channel_new(
164  FL_BINARY_MESSENGER(messenger), "test", FL_METHOD_CODEC(codec));
165 
167  channel, "Test", nullptr, nullptr,
168  [](GObject* object, GAsyncResult* result, gpointer user_data) {
169  g_autoptr(GError) error = nullptr;
170  g_autoptr(FlMethodResponse) response =
171  fl_method_channel_invoke_method_finish(FL_METHOD_CHANNEL(object),
172  result, &error);
173  EXPECT_NE(response, nullptr);
174  EXPECT_EQ(error, nullptr);
175 
176  EXPECT_TRUE(FL_IS_METHOD_NOT_IMPLEMENTED_RESPONSE(response));
177 
178  g_main_loop_quit(static_cast<GMainLoop*>(user_data));
179  },
180  loop);
181 
182  g_main_loop_run(loop);
183 }
184 
185 // Checks if an engine failure calling a method call is handled.
186 TEST_F(FlMethodChannelTest, InvokeMethodFailure) {
187  fl_mock_binary_messenger_set_error_channel(messenger, "test", 42, "ERROR");
188 
189  g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
190  g_autoptr(FlMethodChannel) channel = fl_method_channel_new(
191  FL_BINARY_MESSENGER(messenger), "test", FL_METHOD_CODEC(codec));
192 
194  channel, "Test", nullptr, nullptr,
195  [](GObject* object, GAsyncResult* result, gpointer user_data) {
196  g_autoptr(GError) error = nullptr;
197  g_autoptr(FlMethodResponse) response =
198  fl_method_channel_invoke_method_finish(FL_METHOD_CHANNEL(object),
199  result, &error);
200  EXPECT_EQ(response, nullptr);
201  EXPECT_NE(error, nullptr);
202 
203  EXPECT_EQ(error->code, 42);
204  EXPECT_STREQ(error->message, "ERROR");
205 
206  g_main_loop_quit(static_cast<GMainLoop*>(user_data));
207  },
208  loop);
209 
210  g_main_loop_run(loop);
211 }
212 
213 // Checks the shell able to receive and respond to method calls from the engine.
214 TEST_F(FlMethodChannelTest, ReceiveMethodCallRespondSuccess) {
215  g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
216  g_autoptr(FlMethodChannel) channel = fl_method_channel_new(
217  FL_BINARY_MESSENGER(messenger), "test", FL_METHOD_CODEC(codec));
219  channel,
220  [](FlMethodChannel* channel, FlMethodCall* method_call,
221  gpointer user_data) {
222  EXPECT_STREQ(fl_method_call_get_name(method_call), "Test");
226  "Marco!");
227 
228  g_autoptr(FlValue) result = fl_value_new_string("Polo!");
229  g_autoptr(GError) error = nullptr;
230  EXPECT_TRUE(
232  EXPECT_EQ(error, nullptr);
233  },
234  nullptr, nullptr);
235 
236  // Trigger the engine to make a method call.
238  gboolean called = FALSE;
239  fl_mock_binary_messenger_invoke_standard_method(
240  messenger, "test", "Test", args,
241  [](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
242  gpointer user_data) {
243  gboolean* called = static_cast<gboolean*>(user_data);
244  *called = TRUE;
245 
246  EXPECT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response));
248  FL_METHOD_SUCCESS_RESPONSE(response));
249  EXPECT_EQ(fl_value_get_type(result), FL_VALUE_TYPE_STRING);
250  EXPECT_STREQ(fl_value_get_string(result), "Polo!");
251  },
252  &called);
253  EXPECT_TRUE(called);
254 }
255 
256 // Checks the shell able to receive and respond to method calls from the engine.
257 TEST_F(FlMethodChannelTest, ReceiveMethodCallRespondError) {
258  g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
259  g_autoptr(FlMethodChannel) channel = fl_method_channel_new(
260  FL_BINARY_MESSENGER(messenger), "test", FL_METHOD_CODEC(codec));
262  channel,
263  [](FlMethodChannel* channel, FlMethodCall* method_call,
264  gpointer user_data) {
265  EXPECT_STREQ(fl_method_call_get_name(method_call), "Test");
269  "Marco!");
270 
271  g_autoptr(FlValue) details = fl_value_new_string("DETAILS");
272  g_autoptr(GError) error = nullptr;
273  EXPECT_TRUE(fl_method_call_respond_error(method_call, "CODE", "MESSAGE",
274  details, &error));
275  EXPECT_EQ(error, nullptr);
276  },
277  nullptr, nullptr);
278 
279  // Trigger the engine to make a method call.
281  gboolean called = FALSE;
282  fl_mock_binary_messenger_invoke_standard_method(
283  messenger, "test", "Test", args,
284  [](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
285  gpointer user_data) {
286  gboolean* called = static_cast<gboolean*>(user_data);
287  *called = TRUE;
288 
289  EXPECT_TRUE(FL_IS_METHOD_ERROR_RESPONSE(response));
291  FL_METHOD_ERROR_RESPONSE(response)),
292  "CODE");
294  FL_METHOD_ERROR_RESPONSE(response)),
295  "MESSAGE");
297  FL_METHOD_ERROR_RESPONSE(response));
298  EXPECT_EQ(fl_value_get_type(details), FL_VALUE_TYPE_STRING);
299  EXPECT_STREQ(fl_value_get_string(details), "DETAILS");
300  },
301  &called);
302  EXPECT_TRUE(called);
303 }
304 
305 // Checks the shell able to receive and respond to method calls from the engine.
306 TEST_F(FlMethodChannelTest, ReceiveMethodCallRespondNotImplemented) {
307  g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
308  g_autoptr(FlMethodChannel) channel = fl_method_channel_new(
309  FL_BINARY_MESSENGER(messenger), "test", FL_METHOD_CODEC(codec));
311  channel,
312  [](FlMethodChannel* channel, FlMethodCall* method_call,
313  gpointer user_data) {
314  EXPECT_STREQ(fl_method_call_get_name(method_call), "Test");
318  "Marco!");
319 
320  g_autoptr(GError) error = nullptr;
321  EXPECT_TRUE(
323  EXPECT_EQ(error, nullptr);
324  },
325  nullptr, nullptr);
326 
327  // Trigger the engine to make a method call.
329  gboolean called = FALSE;
330  fl_mock_binary_messenger_invoke_standard_method(
331  messenger, "test", "Test", args,
332  [](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
333  gpointer user_data) {
334  gboolean* called = static_cast<gboolean*>(user_data);
335  *called = TRUE;
336 
337  EXPECT_TRUE(FL_IS_METHOD_NOT_IMPLEMENTED_RESPONSE(response));
338  },
339  &called);
340  EXPECT_TRUE(called);
341 }
342 
343 // A test method codec that always generates errors on responses.
344 G_DECLARE_FINAL_TYPE(TestMethodCodec,
345  test_method_codec,
346  TEST,
347  METHOD_CODEC,
348  FlMethodCodec)
349 
350 struct _TestMethodCodec {
351  FlMethodCodec parent_instance;
352 
353  FlStandardMethodCodec* wrapped_codec;
354 };
355 
356 G_DEFINE_TYPE(TestMethodCodec, test_method_codec, fl_method_codec_get_type())
357 
358 static void test_method_codec_dispose(GObject* object) {
359  TestMethodCodec* self = TEST_METHOD_CODEC(object);
360 
361  g_clear_object(&self->wrapped_codec);
362 
363  G_OBJECT_CLASS(test_method_codec_parent_class)->dispose(object);
364 }
365 
366 // Implements FlMethodCodec::encode_method_call.
367 static GBytes* test_method_codec_encode_method_call(FlMethodCodec* codec,
368  const gchar* name,
369  FlValue* args,
370  GError** error) {
371  EXPECT_TRUE(TEST_IS_METHOD_CODEC(codec));
372  TestMethodCodec* self = TEST_METHOD_CODEC(codec);
374  FL_METHOD_CODEC(self->wrapped_codec), name, args, error);
375 }
376 
377 // Implements FlMethodCodec::decode_method_call.
378 static gboolean test_method_codec_decode_method_call(FlMethodCodec* codec,
379  GBytes* message,
380  gchar** name,
381  FlValue** args,
382  GError** error) {
383  EXPECT_TRUE(TEST_IS_METHOD_CODEC(codec));
384  TestMethodCodec* self = TEST_METHOD_CODEC(codec);
386  FL_METHOD_CODEC(self->wrapped_codec), message, name, args, error);
387 }
388 
389 // Implements FlMethodCodec::encode_success_envelope.
390 static GBytes* test_method_codec_encode_success_envelope(FlMethodCodec* codec,
391  FlValue* result,
392  GError** error) {
394  "Unsupported type");
395  return nullptr;
396 }
397 
398 // Implements FlMethodCodec::encode_error_envelope.
399 static GBytes* test_method_codec_encode_error_envelope(FlMethodCodec* codec,
400  const gchar* code,
401  const gchar* message,
402  FlValue* details,
403  GError** error) {
405  "Unsupported type");
406  return nullptr;
407 }
408 
409 // Implements FlMethodCodec::encode_decode_response.
410 static FlMethodResponse* test_method_codec_decode_response(FlMethodCodec* codec,
411  GBytes* message,
412  GError** error) {
413  EXPECT_TRUE(TEST_IS_METHOD_CODEC(codec));
414  TestMethodCodec* self = TEST_METHOD_CODEC(codec);
415  return fl_method_codec_decode_response(FL_METHOD_CODEC(self->wrapped_codec),
416  message, error);
417 }
418 
419 static void test_method_codec_class_init(TestMethodCodecClass* klass) {
420  G_OBJECT_CLASS(klass)->dispose = test_method_codec_dispose;
421  FL_METHOD_CODEC_CLASS(klass)->encode_method_call =
423  FL_METHOD_CODEC_CLASS(klass)->decode_method_call =
425  FL_METHOD_CODEC_CLASS(klass)->encode_success_envelope =
427  FL_METHOD_CODEC_CLASS(klass)->encode_error_envelope =
429  FL_METHOD_CODEC_CLASS(klass)->decode_response =
431 }
432 
433 static void test_method_codec_init(TestMethodCodec* self) {
434  self->wrapped_codec = fl_standard_method_codec_new();
435 }
436 
437 TestMethodCodec* test_method_codec_new() {
438  return TEST_METHOD_CODEC(g_object_new(test_method_codec_get_type(), nullptr));
439 }
440 
441 // Checks error correctly handled if provide an unsupported arg in a method call
442 // response.
443 TEST_F(FlMethodChannelTest, ReceiveMethodCallRespondSuccessError) {
444  g_autoptr(TestMethodCodec) codec = test_method_codec_new();
445  g_autoptr(FlMethodChannel) channel = fl_method_channel_new(
446  FL_BINARY_MESSENGER(messenger), "test", FL_METHOD_CODEC(codec));
447  gboolean called = FALSE;
449  channel,
450  [](FlMethodChannel* channel, FlMethodCall* method_call,
451  gpointer user_data) {
452  gboolean* called = static_cast<gboolean*>(user_data);
453  *called = TRUE;
454 
455  g_autoptr(FlValue) result = fl_value_new_int(42);
456  g_autoptr(GError) response_error = nullptr;
457  EXPECT_FALSE(fl_method_call_respond_success(method_call, result,
458  &response_error));
459  EXPECT_NE(response_error, nullptr);
460  EXPECT_STREQ(response_error->message, "Unsupported type");
461 
462  // Respond to stop a warning occurring about not responding.
464  },
465  &called, nullptr);
466 
467  // Trigger the engine to make a method call.
468  fl_mock_binary_messenger_invoke_standard_method(
469  messenger, "test", "Test", nullptr,
470  [](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
471  gpointer user_data) {},
472  nullptr);
473 
474  EXPECT_TRUE(called);
475 }
476 
477 // Checks error correctly handled if provide an unsupported arg in a method call
478 // response.
479 TEST_F(FlMethodChannelTest, ReceiveMethodCallRespondErrorError) {
480  g_autoptr(TestMethodCodec) codec = test_method_codec_new();
481  g_autoptr(FlMethodChannel) channel = fl_method_channel_new(
482  FL_BINARY_MESSENGER(messenger), "test", FL_METHOD_CODEC(codec));
483  gboolean called = FALSE;
485  channel,
486  [](FlMethodChannel* channel, FlMethodCall* method_call,
487  gpointer user_data) {
488  gboolean* called = static_cast<gboolean*>(user_data);
489  *called = TRUE;
490 
491  g_autoptr(FlValue) details = fl_value_new_int(42);
492  g_autoptr(GError) response_error = nullptr;
493  EXPECT_FALSE(fl_method_call_respond_error(method_call, "error", "ERROR",
494  details, &response_error));
495  EXPECT_NE(response_error, nullptr);
496  EXPECT_STREQ(response_error->message, "Unsupported type");
497  },
498  &called, nullptr);
499 
500  // Trigger the engine to make a method call.
501  fl_mock_binary_messenger_invoke_standard_method(messenger, "test", "Test",
502  nullptr, nullptr, nullptr);
503 
504  EXPECT_TRUE(called);
505 }
506 
507 // Make sure that the following steps will work properly:
508 //
509 // 1. Register a method channel.
510 // 2. Dispose the method channel, and it's unregistered.
511 // 3. Register a new channel with the same name.
512 //
513 // This is a regression test to https://github.com/flutter/flutter/issues/90817.
514 TEST_F(FlMethodChannelTest, ReplaceADisposedMethodChannel) {
515  g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
516 
517  // Register the first channel and test if it works.
518  FlMethodChannel* channel1 = fl_method_channel_new(
519  FL_BINARY_MESSENGER(messenger), "test", FL_METHOD_CODEC(codec));
520  int first_count = 0;
522  channel1,
523  [](FlMethodChannel* channel, FlMethodCall* method_call,
524  gpointer user_data) {
525  int* first_count = static_cast<int*>(user_data);
526  (*first_count)++;
527 
528  EXPECT_TRUE(
529  fl_method_call_respond_success(method_call, nullptr, nullptr));
530  },
531  &first_count, nullptr);
532 
533  fl_mock_binary_messenger_invoke_standard_method(
534  messenger, "test", "Test", nullptr,
535  [](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
536  gpointer user_data) {},
537  nullptr);
538  EXPECT_EQ(first_count, 1);
539 
540  // Dispose the first channel.
541  g_object_unref(channel1);
542 
543  // Register the second channel and test if it works.
544  g_autoptr(FlMethodChannel) channel2 = fl_method_channel_new(
545  FL_BINARY_MESSENGER(messenger), "test", FL_METHOD_CODEC(codec));
546  int second_count = 0;
548  channel2,
549  [](FlMethodChannel* channel, FlMethodCall* method_call,
550  gpointer user_data) {
551  int* second_count = static_cast<int*>(user_data);
552  (*second_count)++;
553 
554  EXPECT_TRUE(
555  fl_method_call_respond_success(method_call, nullptr, nullptr));
556  },
557  &second_count, nullptr);
558 
559  fl_mock_binary_messenger_invoke_standard_method(
560  messenger, "test", "Test", nullptr,
561  [](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
562  gpointer user_data) {},
563  nullptr);
564  EXPECT_EQ(first_count, 1);
565  EXPECT_EQ(second_count, 1);
566 }
567 
568 // Make sure that the following steps will work properly:
569 //
570 // 1. Register a method channel.
571 // 2. Register the same name with a new channel.
572 // 3. Dispose the previous method channel.
573 //
574 // This is a regression test to https://github.com/flutter/flutter/issues/90817.
575 TEST_F(FlMethodChannelTest, DisposeAReplacedMethodChannel) {
576  g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
577 
578  // Register the first channel and test if it works.
579  FlMethodChannel* channel1 = fl_method_channel_new(
580  FL_BINARY_MESSENGER(messenger), "test", FL_METHOD_CODEC(codec));
581  int first_count = 0;
583  channel1,
584  [](FlMethodChannel* channel, FlMethodCall* method_call,
585  gpointer user_data) {
586  int* first_count = static_cast<int*>(user_data);
587  (*first_count)++;
588 
589  EXPECT_TRUE(
590  fl_method_call_respond_success(method_call, nullptr, nullptr));
591  },
592  &first_count, nullptr);
593 
594  fl_mock_binary_messenger_invoke_standard_method(
595  messenger, "test", "Test", nullptr,
596  [](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
597  gpointer user_data) {},
598  nullptr);
599  EXPECT_EQ(first_count, 1);
600 
601  // Register a new channel to the same name.
602  g_autoptr(FlMethodChannel) channel2 = fl_method_channel_new(
603  FL_BINARY_MESSENGER(messenger), "test", FL_METHOD_CODEC(codec));
604  int second_count = 0;
606  channel2,
607  [](FlMethodChannel* channel, FlMethodCall* method_call,
608  gpointer user_data) {
609  int* second_count = static_cast<int*>(user_data);
610  (*second_count)++;
611 
612  EXPECT_TRUE(
613  fl_method_call_respond_success(method_call, nullptr, nullptr));
614  },
615  &second_count, nullptr);
616 
617  fl_mock_binary_messenger_invoke_standard_method(
618  messenger, "test", "Test", nullptr,
619  [](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
620  gpointer user_data) {},
621  nullptr);
622  EXPECT_EQ(first_count, 1);
623  EXPECT_EQ(second_count, 1);
624 
625  // Dispose the first channel. The new channel should keep working.
626  g_object_unref(channel1);
627 
628  fl_mock_binary_messenger_invoke_standard_method(
629  messenger, "test", "Test", nullptr,
630  [](FlMockBinaryMessenger* messenger, FlMethodResponse* response,
631  gpointer user_data) {},
632  nullptr);
633  EXPECT_EQ(first_count, 1);
634  EXPECT_EQ(second_count, 2);
635 }
636 
637 // Checks invoking a method with a custom type generates an error.
639  fl_mock_binary_messenger_set_standard_method_channel(
640  messenger, "test",
641  [](FlMockBinaryMessenger* messenger, GTask* task, const gchar* name,
642  FlValue* args, gpointer user_data) {
643  return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
644  },
645  nullptr);
646 
647  g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
648  g_autoptr(FlMethodChannel) channel = fl_method_channel_new(
649  FL_BINARY_MESSENGER(messenger), "test", FL_METHOD_CODEC(codec));
650 
651  g_autoptr(FlValue) args = fl_value_new_custom(42, nullptr, nullptr);
653  channel, "Test", args, nullptr,
654  [](GObject* object, GAsyncResult* result, gpointer user_data) {
655  g_autoptr(GError) error = nullptr;
656  g_autoptr(FlMethodResponse) response =
657  fl_method_channel_invoke_method_finish(FL_METHOD_CHANNEL(object),
658  result, &error);
659  EXPECT_EQ(response, nullptr);
660  EXPECT_NE(error, nullptr);
661  EXPECT_STREQ(error->message, "Custom value not implemented");
662 
663  g_main_loop_quit(static_cast<GMainLoop*>(user_data));
664  },
665  loop);
666 
667  g_main_loop_run(loop);
668 }
FlMockBinaryMessenger * messenger
const char * message
g_autoptr(FlEngine) engine
const char FlTextDirection FlAssertiveness gpointer user_data
TEST(FlApplicationTest, ConstructorArgs)
G_DEFINE_TYPE(FlBasicMessageChannelResponseHandle, fl_basic_message_channel_response_handle, G_TYPE_OBJECT) static void fl_basic_message_channel_response_handle_dispose(GObject *object)
return TRUE
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
@ FL_MESSAGE_CODEC_ERROR_FAILED
#define FL_MESSAGE_CODEC_ERROR
G_MODULE_EXPORT gboolean fl_method_call_respond_error(FlMethodCall *self, const gchar *code, const gchar *message, FlValue *details, GError **error)
G_MODULE_EXPORT gboolean fl_method_call_respond_success(FlMethodCall *self, FlValue *result, GError **error)
G_MODULE_EXPORT const gchar * fl_method_call_get_name(FlMethodCall *self)
G_MODULE_EXPORT FlValue * fl_method_call_get_args(FlMethodCall *self)
G_MODULE_EXPORT gboolean fl_method_call_respond_not_implemented(FlMethodCall *self, GError **error)
G_MODULE_EXPORT void fl_method_channel_invoke_method(FlMethodChannel *self, const gchar *method, FlValue *args, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data)
G_MODULE_EXPORT FlMethodChannel * fl_method_channel_new(FlBinaryMessenger *messenger, const gchar *name, FlMethodCodec *codec)
G_MODULE_EXPORT FlMethodResponse * fl_method_channel_invoke_method_finish(FlMethodChannel *self, GAsyncResult *result, GError **error)
G_MODULE_EXPORT void fl_method_channel_set_method_call_handler(FlMethodChannel *self, FlMethodChannelMethodCallHandler handler, gpointer user_data, GDestroyNotify destroy_notify)
G_BEGIN_DECLS G_MODULE_EXPORT FlMethodCall * method_call
TestMethodCodec * test_method_codec_new()
static void test_method_codec_dispose(GObject *object)
TEST_F(FlMethodChannelTest, InvokeMethod)
static gboolean test_method_codec_decode_method_call(FlMethodCodec *codec, GBytes *message, gchar **name, FlValue **args, GError **error)
static FlMethodResponse * test_method_codec_decode_response(FlMethodCodec *codec, GBytes *message, GError **error)
static void test_method_codec_class_init(TestMethodCodecClass *klass)
static void test_method_codec_init(TestMethodCodec *self)
static GBytes * test_method_codec_encode_success_envelope(FlMethodCodec *codec, FlValue *result, GError **error)
static GBytes * test_method_codec_encode_method_call(FlMethodCodec *codec, const gchar *name, FlValue *args, GError **error)
static GBytes * test_method_codec_encode_error_envelope(FlMethodCodec *codec, const gchar *code, const gchar *message, FlValue *details, GError **error)
G_DECLARE_FINAL_TYPE(TestMethodCodec, test_method_codec, TEST, METHOD_CODEC, FlMethodCodec) struct _TestMethodCodec
GBytes * fl_method_codec_encode_method_call(FlMethodCodec *self, const gchar *name, FlValue *args, GError **error)
gboolean fl_method_codec_decode_method_call(FlMethodCodec *self, GBytes *message, gchar **name, FlValue **args, GError **error)
FlMethodResponse * fl_method_codec_decode_response(FlMethodCodec *self, GBytes *message, GError **error)
G_MODULE_EXPORT FlMethodErrorResponse * fl_method_error_response_new(const gchar *code, const gchar *message, FlValue *details)
G_MODULE_EXPORT FlMethodSuccessResponse * fl_method_success_response_new(FlValue *result)
G_MODULE_EXPORT const gchar * fl_method_error_response_get_code(FlMethodErrorResponse *self)
G_MODULE_EXPORT const gchar * fl_method_error_response_get_message(FlMethodErrorResponse *self)
G_MODULE_EXPORT FlValue * fl_method_success_response_get_result(FlMethodSuccessResponse *self)
G_MODULE_EXPORT FlValue * fl_method_response_get_result(FlMethodResponse *self, GError **error)
G_MODULE_EXPORT FlMethodNotImplementedResponse * fl_method_not_implemented_response_new()
G_MODULE_EXPORT FlValue * fl_method_error_response_get_details(FlMethodErrorResponse *self)
const uint8_t uint32_t uint32_t GError ** error
G_MODULE_EXPORT FlStandardMethodCodec * fl_standard_method_codec_new()
G_MODULE_EXPORT FlValue * fl_value_new_custom(int type, gconstpointer value, GDestroyNotify destroy_notify)
Definition: fl_value.cc:374
G_MODULE_EXPORT FlValue * fl_value_new_string(const gchar *value)
Definition: fl_value.cc:276
G_MODULE_EXPORT FlValueType fl_value_get_type(FlValue *self)
Definition: fl_value.cc:466
G_MODULE_EXPORT const gchar * fl_value_get_string(FlValue *self)
Definition: fl_value.cc:682
G_MODULE_EXPORT FlValue * fl_value_new_int(int64_t value)
Definition: fl_value.cc:262
typedefG_BEGIN_DECLS struct _FlValue FlValue
Definition: fl_value.h:42
@ FL_VALUE_TYPE_STRING
Definition: fl_value.h:68
@ FL_VALUE_TYPE_NULL
Definition: fl_value.h:64