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