diff --git a/shell/platform/linux/fl_method_channel_test.cc b/shell/platform/linux/fl_method_channel_test.cc index c7d366cfde60b..2afaea7828ed4 100644 --- a/shell/platform/linux/fl_method_channel_test.cc +++ b/shell/platform/linux/fl_method_channel_test.cc @@ -5,421 +5,350 @@ // Included first as it collides with the X11 headers. #include "gtest/gtest.h" -#include "flutter/shell/platform/linux/fl_binary_messenger_private.h" -#include "flutter/shell/platform/linux/fl_engine_private.h" #include "flutter/shell/platform/linux/fl_method_codec_private.h" -#include "flutter/shell/platform/linux/public/flutter_linux/fl_basic_message_channel.h" #include "flutter/shell/platform/linux/public/flutter_linux/fl_method_channel.h" #include "flutter/shell/platform/linux/public/flutter_linux/fl_standard_method_codec.h" -#include "flutter/shell/platform/linux/testing/fl_test.h" -#include "flutter/shell/platform/linux/testing/mock_renderer.h" - -// Called when the method call response is received in the InvokeMethod -// test. -static void method_response_cb(GObject* object, - GAsyncResult* result, - gpointer user_data) { - g_autoptr(GError) error = nullptr; - g_autoptr(FlMethodResponse) response = fl_method_channel_invoke_method_finish( - FL_METHOD_CHANNEL(object), result, &error); - EXPECT_NE(response, nullptr); - EXPECT_EQ(error, nullptr); - - FlValue* r = fl_method_response_get_result(response, &error); - EXPECT_NE(r, nullptr); - EXPECT_EQ(error, nullptr); - - EXPECT_EQ(fl_value_get_type(r), FL_VALUE_TYPE_STRING); - EXPECT_STREQ(fl_value_get_string(r), "Hello World!"); - - g_main_loop_quit(static_cast(user_data)); -} +#include "flutter/shell/platform/linux/testing/fl_mock_binary_messenger.h" // Checks if invoking a method returns a value. TEST(FlMethodChannelTest, InvokeMethod) { g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0); - g_autoptr(FlEngine) engine = make_mock_engine(); - g_autoptr(FlBinaryMessenger) messenger = fl_binary_messenger_new(engine); + g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new(); + fl_mock_binary_messenger_set_standard_method_channel( + messenger, "test", + [](FlMockBinaryMessenger* messenger, const gchar* name, FlValue* args, + gpointer user_data) { + EXPECT_STREQ(name, "Test"); + EXPECT_EQ(fl_value_get_type(args), FL_VALUE_TYPE_STRING); + EXPECT_STREQ(fl_value_get_string(args), "Marco!"); + g_autoptr(FlValue) return_value = fl_value_new_string("Polo!"); + return FL_METHOD_RESPONSE(fl_method_success_response_new(return_value)); + }, + nullptr); + g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new(); g_autoptr(FlMethodChannel) channel = fl_method_channel_new( - messenger, "test/standard-method", FL_METHOD_CODEC(codec)); + FL_BINARY_MESSENGER(messenger), "test", FL_METHOD_CODEC(codec)); + + g_autoptr(FlValue) args = fl_value_new_string("Marco!"); + fl_method_channel_invoke_method( + channel, "Test", args, nullptr, + [](GObject* object, GAsyncResult* result, gpointer user_data) { + g_autoptr(GError) error = nullptr; + g_autoptr(FlMethodResponse) response = + fl_method_channel_invoke_method_finish(FL_METHOD_CHANNEL(object), + result, &error); + EXPECT_NE(response, nullptr); + EXPECT_EQ(error, nullptr); + + FlValue* r = fl_method_response_get_result(response, &error); + EXPECT_NE(r, nullptr); + EXPECT_EQ(error, nullptr); + + EXPECT_EQ(fl_value_get_type(r), FL_VALUE_TYPE_STRING); + EXPECT_STREQ(fl_value_get_string(r), "Polo!"); + + g_main_loop_quit(static_cast(user_data)); + }, + loop); - g_autoptr(FlValue) args = fl_value_new_string("Hello World!"); - fl_method_channel_invoke_method(channel, "Echo", args, nullptr, - method_response_cb, loop); - - // Blocks here until method_response_cb is called. g_main_loop_run(loop); } -// Called when the method call response is received in the -// InvokeMethodNullptrArgsMessage test. -static void nullptr_args_response_cb(GObject* object, - GAsyncResult* result, - gpointer user_data) { - g_autoptr(GError) error = nullptr; - g_autoptr(FlMethodResponse) response = fl_method_channel_invoke_method_finish( - FL_METHOD_CHANNEL(object), result, &error); - EXPECT_NE(response, nullptr); - EXPECT_EQ(error, nullptr); - - FlValue* r = fl_method_response_get_result(response, &error); - EXPECT_NE(r, nullptr); - EXPECT_EQ(error, nullptr); - EXPECT_EQ(fl_value_get_type(r), FL_VALUE_TYPE_NULL); - - g_main_loop_quit(static_cast(user_data)); -} - // Checks if a method can be invoked with nullptr for arguments. TEST(FlMethodChannelTest, InvokeMethodNullptrArgsMessage) { g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0); - g_autoptr(FlEngine) engine = make_mock_engine(); - g_autoptr(FlBinaryMessenger) messenger = fl_binary_messenger_new(engine); + g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new(); + fl_mock_binary_messenger_set_standard_method_channel( + messenger, "test", + [](FlMockBinaryMessenger* messenger, const gchar* name, FlValue* args, + gpointer user_data) { + EXPECT_STREQ(name, "Test"); + EXPECT_EQ(fl_value_get_type(args), FL_VALUE_TYPE_NULL); + return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr)); + }, + nullptr); + g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new(); g_autoptr(FlMethodChannel) channel = fl_method_channel_new( - messenger, "test/standard-method", FL_METHOD_CODEC(codec)); - - fl_method_channel_invoke_method(channel, "Echo", nullptr, nullptr, - nullptr_args_response_cb, loop); + FL_BINARY_MESSENGER(messenger), "test", FL_METHOD_CODEC(codec)); + + fl_method_channel_invoke_method( + channel, "Test", nullptr, nullptr, + [](GObject* object, GAsyncResult* result, gpointer user_data) { + g_autoptr(GError) error = nullptr; + g_autoptr(FlMethodResponse) response = + fl_method_channel_invoke_method_finish(FL_METHOD_CHANNEL(object), + result, &error); + EXPECT_NE(response, nullptr); + EXPECT_EQ(error, nullptr); + + FlValue* r = fl_method_response_get_result(response, &error); + EXPECT_NE(r, nullptr); + EXPECT_EQ(error, nullptr); + EXPECT_EQ(fl_value_get_type(r), FL_VALUE_TYPE_NULL); + + g_main_loop_quit(static_cast(user_data)); + }, + loop); - // Blocks here until nullptr_args_response_cb is called. g_main_loop_run(loop); } -// Called when the method call response is received in the -// InvokeMethodError test. -static void error_response_cb(GObject* object, - GAsyncResult* result, - gpointer user_data) { - g_autoptr(GError) error = nullptr; - g_autoptr(FlMethodResponse) response = fl_method_channel_invoke_method_finish( - FL_METHOD_CHANNEL(object), result, &error); - EXPECT_NE(response, nullptr); - EXPECT_EQ(error, nullptr); - - EXPECT_TRUE(FL_IS_METHOD_ERROR_RESPONSE(response)); - EXPECT_STREQ( - fl_method_error_response_get_code(FL_METHOD_ERROR_RESPONSE(response)), - "CODE"); - EXPECT_STREQ( - fl_method_error_response_get_message(FL_METHOD_ERROR_RESPONSE(response)), - "MESSAGE"); - FlValue* details = - fl_method_error_response_get_details(FL_METHOD_ERROR_RESPONSE(response)); - EXPECT_NE(details, nullptr); - EXPECT_EQ(fl_value_get_type(details), FL_VALUE_TYPE_STRING); - EXPECT_STREQ(fl_value_get_string(details), "DETAILS"); - - g_main_loop_quit(static_cast(user_data)); -} - // Checks if an error response from a method call is handled. TEST(FlMethodChannelTest, InvokeMethodError) { g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0); - g_autoptr(FlEngine) engine = make_mock_engine(); - g_autoptr(FlBinaryMessenger) messenger = fl_binary_messenger_new(engine); + g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new(); + fl_mock_binary_messenger_set_standard_method_channel( + messenger, "test", + [](FlMockBinaryMessenger* messenger, const gchar* name, FlValue* args, + gpointer user_data) { + EXPECT_STREQ(name, "Test"); + g_autoptr(FlValue) details = fl_value_new_string("DETAILS"); + return FL_METHOD_RESPONSE( + fl_method_error_response_new("CODE", "MESSAGE", details)); + }, + nullptr); + g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new(); g_autoptr(FlMethodChannel) channel = fl_method_channel_new( - messenger, "test/standard-method", FL_METHOD_CODEC(codec)); - - g_autoptr(FlValue) args = fl_value_new_list(); - fl_value_append_take(args, fl_value_new_string("CODE")); - fl_value_append_take(args, fl_value_new_string("MESSAGE")); - fl_value_append_take(args, fl_value_new_string("DETAILS")); - fl_method_channel_invoke_method(channel, "Error", args, nullptr, - error_response_cb, loop); + FL_BINARY_MESSENGER(messenger), "test", FL_METHOD_CODEC(codec)); + + fl_method_channel_invoke_method( + channel, "Test", nullptr, nullptr, + [](GObject* object, GAsyncResult* result, gpointer user_data) { + g_autoptr(GError) error = nullptr; + g_autoptr(FlMethodResponse) response = + fl_method_channel_invoke_method_finish(FL_METHOD_CHANNEL(object), + result, &error); + EXPECT_NE(response, nullptr); + EXPECT_EQ(error, nullptr); + + EXPECT_TRUE(FL_IS_METHOD_ERROR_RESPONSE(response)); + EXPECT_STREQ(fl_method_error_response_get_code( + FL_METHOD_ERROR_RESPONSE(response)), + "CODE"); + EXPECT_STREQ(fl_method_error_response_get_message( + FL_METHOD_ERROR_RESPONSE(response)), + "MESSAGE"); + FlValue* details = fl_method_error_response_get_details( + FL_METHOD_ERROR_RESPONSE(response)); + EXPECT_NE(details, nullptr); + EXPECT_EQ(fl_value_get_type(details), FL_VALUE_TYPE_STRING); + EXPECT_STREQ(fl_value_get_string(details), "DETAILS"); + + g_main_loop_quit(static_cast(user_data)); + }, + loop); - // Blocks here until error_response_cb is called. g_main_loop_run(loop); } -// Called when the method call response is received in the -// InvokeMethodNotImplemented test. -static void not_implemented_response_cb(GObject* object, - GAsyncResult* result, - gpointer user_data) { - g_autoptr(GError) error = nullptr; - g_autoptr(FlMethodResponse) response = fl_method_channel_invoke_method_finish( - FL_METHOD_CHANNEL(object), result, &error); - EXPECT_NE(response, nullptr); - EXPECT_EQ(error, nullptr); - - EXPECT_TRUE(FL_IS_METHOD_NOT_IMPLEMENTED_RESPONSE(response)); - - g_main_loop_quit(static_cast(user_data)); -} - // Checks if a not implemeneted response from a method call is handled. TEST(FlMethodChannelTest, InvokeMethodNotImplemented) { g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0); - g_autoptr(FlEngine) engine = make_mock_engine(); - g_autoptr(FlBinaryMessenger) messenger = fl_binary_messenger_new(engine); + g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new(); + fl_mock_binary_messenger_set_standard_method_channel( + messenger, "test", + [](FlMockBinaryMessenger* messenger, const gchar* name, FlValue* args, + gpointer user_data) { + EXPECT_STREQ(name, "Test"); + return FL_METHOD_RESPONSE(fl_method_not_implemented_response_new()); + }, + nullptr); + g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new(); g_autoptr(FlMethodChannel) channel = fl_method_channel_new( - messenger, "test/standard-method", FL_METHOD_CODEC(codec)); + FL_BINARY_MESSENGER(messenger), "test", FL_METHOD_CODEC(codec)); - fl_method_channel_invoke_method(channel, "NotImplemented", nullptr, nullptr, - not_implemented_response_cb, loop); + fl_method_channel_invoke_method( + channel, "Test", nullptr, nullptr, + [](GObject* object, GAsyncResult* result, gpointer user_data) { + g_autoptr(GError) error = nullptr; + g_autoptr(FlMethodResponse) response = + fl_method_channel_invoke_method_finish(FL_METHOD_CHANNEL(object), + result, &error); + EXPECT_NE(response, nullptr); + EXPECT_EQ(error, nullptr); - // Blocks here until not_implemented_response_cb is called. - g_main_loop_run(loop); -} + EXPECT_TRUE(FL_IS_METHOD_NOT_IMPLEMENTED_RESPONSE(response)); + + g_main_loop_quit(static_cast(user_data)); + }, + loop); -// Called when the method call response is received in the -// InvokeMethodFailure test. -static void failure_response_cb(GObject* object, - GAsyncResult* result, - gpointer user_data) { - g_autoptr(GError) error = nullptr; - g_autoptr(FlMethodResponse) response = fl_method_channel_invoke_method_finish( - FL_METHOD_CHANNEL(object), result, &error); - EXPECT_EQ(response, nullptr); - EXPECT_NE(error, nullptr); - - g_main_loop_quit(static_cast(user_data)); + g_main_loop_run(loop); } // Checks if an engine failure calling a method call is handled. TEST(FlMethodChannelTest, InvokeMethodFailure) { g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0); - g_autoptr(FlEngine) engine = make_mock_engine(); - g_autoptr(FlBinaryMessenger) messenger = fl_binary_messenger_new(engine); + g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new(); + fl_mock_binary_messenger_set_error_channel(messenger, "test", 42, "ERROR"); + g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new(); - g_autoptr(FlMethodChannel) channel = - fl_method_channel_new(messenger, "test/failure", FL_METHOD_CODEC(codec)); + g_autoptr(FlMethodChannel) channel = fl_method_channel_new( + FL_BINARY_MESSENGER(messenger), "test", FL_METHOD_CODEC(codec)); - fl_method_channel_invoke_method(channel, "Echo", nullptr, nullptr, - failure_response_cb, loop); + fl_method_channel_invoke_method( + channel, "Test", nullptr, nullptr, + [](GObject* object, GAsyncResult* result, gpointer user_data) { + g_autoptr(GError) error = nullptr; + g_autoptr(FlMethodResponse) response = + fl_method_channel_invoke_method_finish(FL_METHOD_CHANNEL(object), + result, &error); + EXPECT_EQ(response, nullptr); + EXPECT_NE(error, nullptr); - // Blocks here until failure_response_cb is called. - g_main_loop_run(loop); -} + EXPECT_EQ(error->code, 42); + EXPECT_STREQ(error->message, "ERROR"); -// Called when a method call is received from the engine in the -// ReceiveMethodCallRespondSuccess test. -static void method_call_success_cb(FlMethodChannel* channel, - FlMethodCall* method_call, - gpointer user_data) { - EXPECT_STREQ(fl_method_call_get_name(method_call), "Foo"); - EXPECT_EQ(fl_value_get_type(fl_method_call_get_args(method_call)), - FL_VALUE_TYPE_STRING); - EXPECT_STREQ(fl_value_get_string(fl_method_call_get_args(method_call)), - "Marco!"); - - g_autoptr(FlValue) result = fl_value_new_string("Polo!"); - g_autoptr(GError) error = nullptr; - EXPECT_TRUE(fl_method_call_respond_success(method_call, result, &error)); - EXPECT_EQ(error, nullptr); -} + g_main_loop_quit(static_cast(user_data)); + }, + loop); -// Called when a the test engine notifies us what response we sent in the -// ReceiveMethodCallRespondSuccess test. -static void method_call_success_response_cb( - FlBinaryMessenger* messenger, - const gchar* channel, - GBytes* message, - FlBinaryMessengerResponseHandle* response_handle, - gpointer user_data) { - g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new(); - g_autoptr(GError) error = nullptr; - g_autoptr(FlMethodResponse) response = - fl_method_codec_decode_response(FL_METHOD_CODEC(codec), message, &error); - EXPECT_NE(response, nullptr); - EXPECT_EQ(error, nullptr); - - EXPECT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response)); - FlValue* result = fl_method_success_response_get_result( - FL_METHOD_SUCCESS_RESPONSE(response)); - EXPECT_EQ(fl_value_get_type(result), FL_VALUE_TYPE_STRING); - EXPECT_STREQ(fl_value_get_string(result), "Polo!"); - - fl_binary_messenger_send_response(messenger, response_handle, nullptr, - nullptr); - - g_main_loop_quit(static_cast(user_data)); + g_main_loop_run(loop); } // Checks the shell able to receive and respond to method calls from the engine. TEST(FlMethodChannelTest, ReceiveMethodCallRespondSuccess) { - g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0); + g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new(); - g_autoptr(FlEngine) engine = make_mock_engine(); - g_autoptr(FlBinaryMessenger) messenger = fl_binary_messenger_new(engine); g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new(); g_autoptr(FlMethodChannel) channel = fl_method_channel_new( - messenger, "test/standard-method", FL_METHOD_CODEC(codec)); - fl_method_channel_set_method_call_handler(channel, method_call_success_cb, - nullptr, nullptr); - - // Listen for response from the engine. - fl_binary_messenger_set_message_handler_on_channel( - messenger, "test/responses", method_call_success_response_cb, loop, - nullptr); + FL_BINARY_MESSENGER(messenger), "test", FL_METHOD_CODEC(codec)); + fl_method_channel_set_method_call_handler( + channel, + [](FlMethodChannel* channel, FlMethodCall* method_call, + gpointer user_data) { + EXPECT_STREQ(fl_method_call_get_name(method_call), "Test"); + EXPECT_EQ(fl_value_get_type(fl_method_call_get_args(method_call)), + FL_VALUE_TYPE_STRING); + EXPECT_STREQ(fl_value_get_string(fl_method_call_get_args(method_call)), + "Marco!"); + + g_autoptr(FlValue) result = fl_value_new_string("Polo!"); + g_autoptr(GError) error = nullptr; + EXPECT_TRUE( + fl_method_call_respond_success(method_call, result, &error)); + EXPECT_EQ(error, nullptr); + }, + nullptr, nullptr); // Trigger the engine to make a method call. - g_autoptr(FlValue) args = fl_value_new_list(); - fl_value_append_take(args, fl_value_new_string("test/standard-method")); - fl_value_append_take(args, fl_value_new_string("Foo")); - fl_value_append_take(args, fl_value_new_string("Marco!")); - fl_method_channel_invoke_method(channel, "InvokeMethod", args, nullptr, - nullptr, loop); - - // Blocks here until method_call_success_response_cb is called. - g_main_loop_run(loop); -} - -// Called when a method call is received from the engine in the -// ReceiveMethodCallRespondError test. -static void method_call_error_cb(FlMethodChannel* channel, - FlMethodCall* method_call, - gpointer user_data) { - EXPECT_STREQ(fl_method_call_get_name(method_call), "Foo"); - EXPECT_EQ(fl_value_get_type(fl_method_call_get_args(method_call)), - FL_VALUE_TYPE_STRING); - EXPECT_STREQ(fl_value_get_string(fl_method_call_get_args(method_call)), - "Marco!"); - - g_autoptr(FlValue) details = fl_value_new_string("DETAILS"); - g_autoptr(GError) error = nullptr; - EXPECT_TRUE(fl_method_call_respond_error(method_call, "CODE", "MESSAGE", - details, &error)); - EXPECT_EQ(error, nullptr); -} - -// Called when a the test engine notifies us what response we sent in the -// ReceiveMethodCallRespondError test. -static void method_call_error_response_cb( - FlBinaryMessenger* messenger, - const gchar* channel, - GBytes* message, - FlBinaryMessengerResponseHandle* response_handle, - gpointer user_data) { - g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new(); - g_autoptr(GError) error = nullptr; - g_autoptr(FlMethodResponse) response = - fl_method_codec_decode_response(FL_METHOD_CODEC(codec), message, &error); - EXPECT_NE(response, nullptr); - EXPECT_EQ(error, nullptr); - - EXPECT_TRUE(FL_IS_METHOD_ERROR_RESPONSE(response)); - EXPECT_STREQ( - fl_method_error_response_get_code(FL_METHOD_ERROR_RESPONSE(response)), - "CODE"); - EXPECT_STREQ( - fl_method_error_response_get_message(FL_METHOD_ERROR_RESPONSE(response)), - "MESSAGE"); - FlValue* details = - fl_method_error_response_get_details(FL_METHOD_ERROR_RESPONSE(response)); - EXPECT_EQ(fl_value_get_type(details), FL_VALUE_TYPE_STRING); - EXPECT_STREQ(fl_value_get_string(details), "DETAILS"); - - fl_binary_messenger_send_response(messenger, response_handle, nullptr, - nullptr); - - g_main_loop_quit(static_cast(user_data)); + g_autoptr(FlValue) args = fl_value_new_string("Marco!"); + gboolean called = FALSE; + fl_mock_binary_messenger_invoke_standard_method( + messenger, "test", "Test", args, + [](FlMockBinaryMessenger* messenger, FlMethodResponse* response, + gpointer user_data) { + gboolean* called = static_cast(user_data); + *called = TRUE; + + EXPECT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response)); + FlValue* result = fl_method_success_response_get_result( + FL_METHOD_SUCCESS_RESPONSE(response)); + EXPECT_EQ(fl_value_get_type(result), FL_VALUE_TYPE_STRING); + EXPECT_STREQ(fl_value_get_string(result), "Polo!"); + }, + &called); + EXPECT_TRUE(called); } // Checks the shell able to receive and respond to method calls from the engine. TEST(FlMethodChannelTest, ReceiveMethodCallRespondError) { - g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0); + g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new(); - g_autoptr(FlEngine) engine = make_mock_engine(); - g_autoptr(FlBinaryMessenger) messenger = fl_binary_messenger_new(engine); g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new(); g_autoptr(FlMethodChannel) channel = fl_method_channel_new( - messenger, "test/standard-method", FL_METHOD_CODEC(codec)); - fl_method_channel_set_method_call_handler(channel, method_call_error_cb, - nullptr, nullptr); - - // Listen for response from the engine. - fl_binary_messenger_set_message_handler_on_channel( - messenger, "test/responses", method_call_error_response_cb, loop, - nullptr); + FL_BINARY_MESSENGER(messenger), "test", FL_METHOD_CODEC(codec)); + fl_method_channel_set_method_call_handler( + channel, + [](FlMethodChannel* channel, FlMethodCall* method_call, + gpointer user_data) { + EXPECT_STREQ(fl_method_call_get_name(method_call), "Test"); + EXPECT_EQ(fl_value_get_type(fl_method_call_get_args(method_call)), + FL_VALUE_TYPE_STRING); + EXPECT_STREQ(fl_value_get_string(fl_method_call_get_args(method_call)), + "Marco!"); + + g_autoptr(FlValue) details = fl_value_new_string("DETAILS"); + g_autoptr(GError) error = nullptr; + EXPECT_TRUE(fl_method_call_respond_error(method_call, "CODE", "MESSAGE", + details, &error)); + EXPECT_EQ(error, nullptr); + }, + nullptr, nullptr); // Trigger the engine to make a method call. - g_autoptr(FlValue) args = fl_value_new_list(); - fl_value_append_take(args, fl_value_new_string("test/standard-method")); - fl_value_append_take(args, fl_value_new_string("Foo")); - fl_value_append_take(args, fl_value_new_string("Marco!")); - fl_method_channel_invoke_method(channel, "InvokeMethod", args, nullptr, - nullptr, loop); - - // Blocks here until method_call_error_response_cb is called. - g_main_loop_run(loop); -} - -// Called when a method call is received from the engine in the -// ReceiveMethodCallRespondNotImplemented test. -static void method_call_not_implemented_cb(FlMethodChannel* channel, - FlMethodCall* method_call, - gpointer user_data) { - EXPECT_STREQ(fl_method_call_get_name(method_call), "Foo"); - EXPECT_EQ(fl_value_get_type(fl_method_call_get_args(method_call)), - FL_VALUE_TYPE_STRING); - EXPECT_STREQ(fl_value_get_string(fl_method_call_get_args(method_call)), - "Marco!"); - - g_autoptr(GError) error = nullptr; - EXPECT_TRUE(fl_method_call_respond_not_implemented(method_call, &error)); - EXPECT_EQ(error, nullptr); -} - -// Called when a the test engine notifies us what response we sent in the -// ReceiveMethodCallRespondNotImplemented test. -static void method_call_not_implemented_response_cb( - FlBinaryMessenger* messenger, - const gchar* channel, - GBytes* message, - FlBinaryMessengerResponseHandle* response_handle, - gpointer user_data) { - g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new(); - g_autoptr(GError) error = nullptr; - g_autoptr(FlMethodResponse) response = - fl_method_codec_decode_response(FL_METHOD_CODEC(codec), message, &error); - EXPECT_NE(response, nullptr); - EXPECT_EQ(error, nullptr); - - EXPECT_TRUE(FL_IS_METHOD_NOT_IMPLEMENTED_RESPONSE(response)); - - fl_binary_messenger_send_response(messenger, response_handle, nullptr, - nullptr); - - g_main_loop_quit(static_cast(user_data)); + g_autoptr(FlValue) args = fl_value_new_string("Marco!"); + gboolean called = FALSE; + fl_mock_binary_messenger_invoke_standard_method( + messenger, "test", "Test", args, + [](FlMockBinaryMessenger* messenger, FlMethodResponse* response, + gpointer user_data) { + gboolean* called = static_cast(user_data); + *called = TRUE; + + EXPECT_TRUE(FL_IS_METHOD_ERROR_RESPONSE(response)); + EXPECT_STREQ(fl_method_error_response_get_code( + FL_METHOD_ERROR_RESPONSE(response)), + "CODE"); + EXPECT_STREQ(fl_method_error_response_get_message( + FL_METHOD_ERROR_RESPONSE(response)), + "MESSAGE"); + FlValue* details = fl_method_error_response_get_details( + FL_METHOD_ERROR_RESPONSE(response)); + EXPECT_EQ(fl_value_get_type(details), FL_VALUE_TYPE_STRING); + EXPECT_STREQ(fl_value_get_string(details), "DETAILS"); + }, + &called); + EXPECT_TRUE(called); } // Checks the shell able to receive and respond to method calls from the engine. TEST(FlMethodChannelTest, ReceiveMethodCallRespondNotImplemented) { - g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0); + g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new(); - g_autoptr(FlEngine) engine = make_mock_engine(); - g_autoptr(FlBinaryMessenger) messenger = fl_binary_messenger_new(engine); g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new(); g_autoptr(FlMethodChannel) channel = fl_method_channel_new( - messenger, "test/standard-method", FL_METHOD_CODEC(codec)); + FL_BINARY_MESSENGER(messenger), "test", FL_METHOD_CODEC(codec)); fl_method_channel_set_method_call_handler( - channel, method_call_not_implemented_cb, nullptr, nullptr); - - // Listen for response from the engine. - fl_binary_messenger_set_message_handler_on_channel( - messenger, "test/responses", method_call_not_implemented_response_cb, - loop, nullptr); + channel, + [](FlMethodChannel* channel, FlMethodCall* method_call, + gpointer user_data) { + EXPECT_STREQ(fl_method_call_get_name(method_call), "Test"); + EXPECT_EQ(fl_value_get_type(fl_method_call_get_args(method_call)), + FL_VALUE_TYPE_STRING); + EXPECT_STREQ(fl_value_get_string(fl_method_call_get_args(method_call)), + "Marco!"); + + g_autoptr(GError) error = nullptr; + EXPECT_TRUE( + fl_method_call_respond_not_implemented(method_call, &error)); + EXPECT_EQ(error, nullptr); + }, + nullptr, nullptr); // Trigger the engine to make a method call. - g_autoptr(FlValue) args = fl_value_new_list(); - fl_value_append_take(args, fl_value_new_string("test/standard-method")); - fl_value_append_take(args, fl_value_new_string("Foo")); - fl_value_append_take(args, fl_value_new_string("Marco!")); - fl_method_channel_invoke_method(channel, "InvokeMethod", args, nullptr, - nullptr, loop); - - // Blocks here until method_call_not_implemented_response_cb is called. - g_main_loop_run(loop); + g_autoptr(FlValue) args = fl_value_new_string("Marco!"); + gboolean called = FALSE; + fl_mock_binary_messenger_invoke_standard_method( + messenger, "test", "Test", args, + [](FlMockBinaryMessenger* messenger, FlMethodResponse* response, + gpointer user_data) { + gboolean* called = static_cast(user_data); + *called = TRUE; + + EXPECT_TRUE(FL_IS_METHOD_NOT_IMPLEMENTED_RESPONSE(response)); + }, + &called); + EXPECT_TRUE(called); } // A test method codec that always generates errors on responses. @@ -520,110 +449,74 @@ TestMethodCodec* test_method_codec_new() { return TEST_METHOD_CODEC(g_object_new(test_method_codec_get_type(), nullptr)); } -// Called when a method call is received from the engine in the -// ReceiveMethodCallRespondSuccessError test. -static void method_call_success_error_cb(FlMethodChannel* channel, - FlMethodCall* method_call, - gpointer user_data) { - g_autoptr(FlValue) result = fl_value_new_int(42); - g_autoptr(GError) response_error = nullptr; - EXPECT_FALSE( - fl_method_call_respond_success(method_call, result, &response_error)); - EXPECT_NE(response_error, nullptr); - - // Respond to stop a warning occurring about not responding. - fl_method_call_respond_not_implemented(method_call, nullptr); - - g_main_loop_quit(static_cast(user_data)); -} - // Checks error correctly handled if provide an unsupported arg in a method call // response. TEST(FlMethodChannelTest, ReceiveMethodCallRespondSuccessError) { - g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0); + g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new(); - g_autoptr(FlEngine) engine = make_mock_engine(); - g_autoptr(FlBinaryMessenger) messenger = fl_binary_messenger_new(engine); g_autoptr(TestMethodCodec) codec = test_method_codec_new(); g_autoptr(FlMethodChannel) channel = fl_method_channel_new( - messenger, "test/standard-method", FL_METHOD_CODEC(codec)); + FL_BINARY_MESSENGER(messenger), "test", FL_METHOD_CODEC(codec)); + gboolean called = FALSE; fl_method_channel_set_method_call_handler( - channel, method_call_success_error_cb, loop, nullptr); + channel, + [](FlMethodChannel* channel, FlMethodCall* method_call, + gpointer user_data) { + gboolean* called = static_cast(user_data); + *called = TRUE; + + g_autoptr(FlValue) result = fl_value_new_int(42); + g_autoptr(GError) response_error = nullptr; + EXPECT_FALSE(fl_method_call_respond_success(method_call, result, + &response_error)); + EXPECT_NE(response_error, nullptr); + EXPECT_STREQ(response_error->message, "Unsupported type"); + + // Respond to stop a warning occurring about not responding. + fl_method_call_respond_not_implemented(method_call, nullptr); + }, + &called, nullptr); // Trigger the engine to make a method call. - g_autoptr(FlValue) args = fl_value_new_list(); - fl_value_append_take(args, fl_value_new_string("test/standard-method")); - fl_value_append_take(args, fl_value_new_string("Foo")); - fl_value_append_take(args, fl_value_new_string("Marco!")); - fl_method_channel_invoke_method(channel, "InvokeMethod", args, nullptr, - nullptr, loop); - - // Blocks here until method_call_success_error_cb is called. - g_main_loop_run(loop); -} + fl_mock_binary_messenger_invoke_standard_method( + messenger, "test", "Test", nullptr, + [](FlMockBinaryMessenger* messenger, FlMethodResponse* response, + gpointer user_data) {}, + nullptr); -// Called when a method call is received from the engine in the -// ReceiveMethodCallRespondErrorError test. -static void method_call_error_error_cb(FlMethodChannel* channel, - FlMethodCall* method_call, - gpointer user_data) { - g_autoptr(FlValue) details = fl_value_new_int(42); - g_autoptr(GError) response_error = nullptr; - EXPECT_FALSE(fl_method_call_respond_error(method_call, "error", "ERROR", - details, &response_error)); - EXPECT_NE(response_error, nullptr); - - // Respond to stop a warning occurring about not responding. - fl_method_call_respond_not_implemented(method_call, nullptr); - - g_main_loop_quit(static_cast(user_data)); + EXPECT_TRUE(called); } // Checks error correctly handled if provide an unsupported arg in a method call // response. TEST(FlMethodChannelTest, ReceiveMethodCallRespondErrorError) { - g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0); + g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new(); - g_autoptr(FlEngine) engine = make_mock_engine(); - g_autoptr(FlBinaryMessenger) messenger = fl_binary_messenger_new(engine); g_autoptr(TestMethodCodec) codec = test_method_codec_new(); g_autoptr(FlMethodChannel) channel = fl_method_channel_new( - messenger, "test/standard-method", FL_METHOD_CODEC(codec)); - fl_method_channel_set_method_call_handler(channel, method_call_error_error_cb, - loop, nullptr); + FL_BINARY_MESSENGER(messenger), "test", FL_METHOD_CODEC(codec)); + gboolean called = FALSE; + fl_method_channel_set_method_call_handler( + channel, + [](FlMethodChannel* channel, FlMethodCall* method_call, + gpointer user_data) { + gboolean* called = static_cast(user_data); + *called = TRUE; + + g_autoptr(FlValue) details = fl_value_new_int(42); + g_autoptr(GError) response_error = nullptr; + EXPECT_FALSE(fl_method_call_respond_error(method_call, "error", "ERROR", + details, &response_error)); + EXPECT_NE(response_error, nullptr); + EXPECT_STREQ(response_error->message, "Unsupported type"); + }, + &called, nullptr); // Trigger the engine to make a method call. - g_autoptr(FlValue) args = fl_value_new_list(); - fl_value_append_take(args, fl_value_new_string("test/standard-method")); - fl_value_append_take(args, fl_value_new_string("Foo")); - fl_value_append_take(args, fl_value_new_string("Marco!")); - fl_method_channel_invoke_method(channel, "InvokeMethod", args, nullptr, - nullptr, loop); - - // Blocks here until method_call_error_error_cb is called. - g_main_loop_run(loop); -} - -struct UserDataReassignMethod { - GMainLoop* loop; - int count; -}; + fl_mock_binary_messenger_invoke_standard_method(messenger, "test", "Test", + nullptr, nullptr, nullptr); -// This callback parses the user data as UserDataReassignMethod, -// increases its `count`, and quits `loop`. -static void reassign_method_cb(FlMethodChannel* channel, - FlMethodCall* method_call, - gpointer raw_user_data) { - UserDataReassignMethod* user_data = - static_cast(raw_user_data); - user_data->count += 1; - - g_autoptr(FlValue) result = fl_value_new_string("Polo!"); - g_autoptr(GError) error = nullptr; - EXPECT_TRUE(fl_method_call_respond_success(method_call, result, &error)); - EXPECT_EQ(error, nullptr); - - g_main_loop_quit(user_data->loop); + EXPECT_TRUE(called); } // Make sure that the following steps will work properly: @@ -634,53 +527,59 @@ static void reassign_method_cb(FlMethodChannel* channel, // // This is a regression test to https://github.com/flutter/flutter/issues/90817. TEST(FlMethodChannelTest, ReplaceADisposedMethodChannel) { - const char* method_name = "test/standard-method"; - // The loop is used to pause the main process until the callback is fully - // executed. - g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0); - g_autoptr(FlEngine) engine = make_mock_engine(); - g_autoptr(FlBinaryMessenger) messenger = fl_binary_messenger_new(engine); - g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new(); + g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new(); - g_autoptr(FlValue) args = fl_value_new_list(); - fl_value_append_take(args, fl_value_new_string(method_name)); - fl_value_append_take(args, fl_value_new_string("FOO")); - fl_value_append_take(args, fl_value_new_string("BAR")); + g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new(); // Register the first channel and test if it works. - UserDataReassignMethod user_data1{ - .loop = loop, - .count = 100, - }; - FlMethodChannel* channel1 = - fl_method_channel_new(messenger, method_name, FL_METHOD_CODEC(codec)); - fl_method_channel_set_method_call_handler(channel1, reassign_method_cb, - &user_data1, nullptr); - - fl_method_channel_invoke_method(channel1, "InvokeMethod", args, nullptr, - nullptr, nullptr); - g_main_loop_run(loop); - EXPECT_EQ(user_data1.count, 101); + FlMethodChannel* channel1 = fl_method_channel_new( + FL_BINARY_MESSENGER(messenger), "test", FL_METHOD_CODEC(codec)); + int first_count = 0; + fl_method_channel_set_method_call_handler( + channel1, + [](FlMethodChannel* channel, FlMethodCall* method_call, + gpointer user_data) { + int* first_count = static_cast(user_data); + (*first_count)++; + + EXPECT_TRUE( + fl_method_call_respond_success(method_call, nullptr, nullptr)); + }, + &first_count, nullptr); + + fl_mock_binary_messenger_invoke_standard_method( + messenger, "test", "Test", nullptr, + [](FlMockBinaryMessenger* messenger, FlMethodResponse* response, + gpointer user_data) {}, + nullptr); + EXPECT_EQ(first_count, 1); // Dispose the first channel. g_object_unref(channel1); // Register the second channel and test if it works. - UserDataReassignMethod user_data2{ - .loop = loop, - .count = 100, - }; - g_autoptr(FlMethodChannel) channel2 = - fl_method_channel_new(messenger, method_name, FL_METHOD_CODEC(codec)); - fl_method_channel_set_method_call_handler(channel2, reassign_method_cb, - &user_data2, nullptr); - - fl_method_channel_invoke_method(channel2, "InvokeMethod", args, nullptr, - nullptr, nullptr); - g_main_loop_run(loop); - - EXPECT_EQ(user_data1.count, 101); - EXPECT_EQ(user_data2.count, 101); + g_autoptr(FlMethodChannel) channel2 = fl_method_channel_new( + FL_BINARY_MESSENGER(messenger), "test", FL_METHOD_CODEC(codec)); + int second_count = 0; + fl_method_channel_set_method_call_handler( + channel2, + [](FlMethodChannel* channel, FlMethodCall* method_call, + gpointer user_data) { + int* second_count = static_cast(user_data); + (*second_count)++; + + EXPECT_TRUE( + fl_method_call_respond_success(method_call, nullptr, nullptr)); + }, + &second_count, nullptr); + + fl_mock_binary_messenger_invoke_standard_method( + messenger, "test", "Test", nullptr, + [](FlMockBinaryMessenger* messenger, FlMethodResponse* response, + gpointer user_data) {}, + nullptr); + EXPECT_EQ(first_count, 1); + EXPECT_EQ(second_count, 1); } // Make sure that the following steps will work properly: @@ -691,89 +590,101 @@ TEST(FlMethodChannelTest, ReplaceADisposedMethodChannel) { // // This is a regression test to https://github.com/flutter/flutter/issues/90817. TEST(FlMethodChannelTest, DisposeAReplacedMethodChannel) { - const char* method_name = "test/standard-method"; - // The loop is used to pause the main process until the callback is fully - // executed. - g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0); - g_autoptr(FlEngine) engine = make_mock_engine(); - g_autoptr(FlBinaryMessenger) messenger = fl_binary_messenger_new(engine); - g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new(); + g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new(); - g_autoptr(FlValue) args = fl_value_new_list(); - fl_value_append_take(args, fl_value_new_string(method_name)); - fl_value_append_take(args, fl_value_new_string("FOO")); - fl_value_append_take(args, fl_value_new_string("BAR")); + g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new(); // Register the first channel and test if it works. - UserDataReassignMethod user_data1{ - .loop = loop, - .count = 100, - }; - FlMethodChannel* channel1 = - fl_method_channel_new(messenger, method_name, FL_METHOD_CODEC(codec)); - fl_method_channel_set_method_call_handler(channel1, reassign_method_cb, - &user_data1, nullptr); - - fl_method_channel_invoke_method(channel1, "InvokeMethod", args, nullptr, - nullptr, nullptr); - g_main_loop_run(loop); - EXPECT_EQ(user_data1.count, 101); + FlMethodChannel* channel1 = fl_method_channel_new( + FL_BINARY_MESSENGER(messenger), "test", FL_METHOD_CODEC(codec)); + int first_count = 0; + fl_method_channel_set_method_call_handler( + channel1, + [](FlMethodChannel* channel, FlMethodCall* method_call, + gpointer user_data) { + int* first_count = static_cast(user_data); + (*first_count)++; + + EXPECT_TRUE( + fl_method_call_respond_success(method_call, nullptr, nullptr)); + }, + &first_count, nullptr); + + fl_mock_binary_messenger_invoke_standard_method( + messenger, "test", "Test", nullptr, + [](FlMockBinaryMessenger* messenger, FlMethodResponse* response, + gpointer user_data) {}, + nullptr); + EXPECT_EQ(first_count, 1); // Register a new channel to the same name. - UserDataReassignMethod user_data2{ - .loop = loop, - .count = 100, - }; - g_autoptr(FlMethodChannel) channel2 = - fl_method_channel_new(messenger, method_name, FL_METHOD_CODEC(codec)); - fl_method_channel_set_method_call_handler(channel2, reassign_method_cb, - &user_data2, nullptr); - - fl_method_channel_invoke_method(channel2, "InvokeMethod", args, nullptr, - nullptr, nullptr); - g_main_loop_run(loop); - EXPECT_EQ(user_data1.count, 101); - EXPECT_EQ(user_data2.count, 101); + g_autoptr(FlMethodChannel) channel2 = fl_method_channel_new( + FL_BINARY_MESSENGER(messenger), "test", FL_METHOD_CODEC(codec)); + int second_count = 0; + fl_method_channel_set_method_call_handler( + channel2, + [](FlMethodChannel* channel, FlMethodCall* method_call, + gpointer user_data) { + int* second_count = static_cast(user_data); + (*second_count)++; + + EXPECT_TRUE( + fl_method_call_respond_success(method_call, nullptr, nullptr)); + }, + &second_count, nullptr); + + fl_mock_binary_messenger_invoke_standard_method( + messenger, "test", "Test", nullptr, + [](FlMockBinaryMessenger* messenger, FlMethodResponse* response, + gpointer user_data) {}, + nullptr); + EXPECT_EQ(first_count, 1); + EXPECT_EQ(second_count, 1); // Dispose the first channel. The new channel should keep working. g_object_unref(channel1); - fl_method_channel_invoke_method(channel2, "InvokeMethod", args, nullptr, - nullptr, nullptr); - g_main_loop_run(loop); - EXPECT_EQ(user_data1.count, 101); - EXPECT_EQ(user_data2.count, 102); -} - -// Called when the method call response is received in the CustomType -// test. -static void custom_type_response_cb(GObject* object, - GAsyncResult* result, - gpointer user_data) { - g_autoptr(GError) error = nullptr; - g_autoptr(FlMethodResponse) response = fl_method_channel_invoke_method_finish( - FL_METHOD_CHANNEL(object), result, &error); - EXPECT_EQ(response, nullptr); - EXPECT_NE(error, nullptr); - EXPECT_STREQ(error->message, "Custom value not implemented"); - - g_main_loop_quit(static_cast(user_data)); + fl_mock_binary_messenger_invoke_standard_method( + messenger, "test", "Test", nullptr, + [](FlMockBinaryMessenger* messenger, FlMethodResponse* response, + gpointer user_data) {}, + nullptr); + EXPECT_EQ(first_count, 1); + EXPECT_EQ(second_count, 2); } // Checks invoking a method with a custom type generates an error. TEST(FlMethodChannelTest, CustomType) { g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0); - g_autoptr(FlEngine) engine = make_mock_engine(); - g_autoptr(FlBinaryMessenger) messenger = fl_binary_messenger_new(engine); + g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new(); + fl_mock_binary_messenger_set_standard_method_channel( + messenger, "test", + [](FlMockBinaryMessenger* messenger, const gchar* name, FlValue* args, + gpointer user_data) { + return FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr)); + }, + nullptr); + g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new(); g_autoptr(FlMethodChannel) channel = fl_method_channel_new( - messenger, "test/standard-method", FL_METHOD_CODEC(codec)); + FL_BINARY_MESSENGER(messenger), "test", FL_METHOD_CODEC(codec)); g_autoptr(FlValue) args = fl_value_new_custom(42, nullptr, nullptr); - fl_method_channel_invoke_method(channel, "Echo", args, nullptr, - custom_type_response_cb, loop); + fl_method_channel_invoke_method( + channel, "Test", args, nullptr, + [](GObject* object, GAsyncResult* result, gpointer user_data) { + g_autoptr(GError) error = nullptr; + g_autoptr(FlMethodResponse) response = + fl_method_channel_invoke_method_finish(FL_METHOD_CHANNEL(object), + result, &error); + EXPECT_EQ(response, nullptr); + EXPECT_NE(error, nullptr); + EXPECT_STREQ(error->message, "Custom value not implemented"); + + g_main_loop_quit(static_cast(user_data)); + }, + loop); - // Blocks here until custom_type_response_cb is called. g_main_loop_run(loop); }