|
7 | 7 |
|
8 | 8 | #include "flutter/shell/platform/linux/public/flutter_linux/fl_basic_message_channel.h" |
9 | 9 |
|
10 | | -#include "flutter/shell/platform/embedder/embedder.h" |
11 | | -#include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h" |
12 | | -#include "flutter/shell/platform/linux/fl_binary_messenger_private.h" |
13 | | -#include "flutter/shell/platform/linux/fl_engine_private.h" |
14 | 10 | #include "flutter/shell/platform/linux/public/flutter_linux/fl_message_codec.h" |
15 | 11 | #include "flutter/shell/platform/linux/public/flutter_linux/fl_standard_message_codec.h" |
16 | | -#include "flutter/shell/platform/linux/testing/fl_test.h" |
17 | | -#include "flutter/shell/platform/linux/testing/mock_renderer.h" |
| 12 | +#include "flutter/shell/platform/linux/testing/fl_mock_binary_messenger.h" |
18 | 13 |
|
19 | 14 | // Checks sending a message without a response works. |
20 | 15 | // MOCK_ENGINE_PROC is leaky by design |
21 | 16 | // NOLINTBEGIN(clang-analyzer-core.StackAddressEscape) |
22 | 17 | TEST(FlBasicMessageChannelTest, SendMessageWithoutResponse) { |
23 | | - g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0); |
| 18 | + g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new(); |
| 19 | + gboolean called = FALSE; |
| 20 | + fl_mock_binary_messenger_set_standard_message_channel( |
| 21 | + messenger, "test", |
| 22 | + [](FlMockBinaryMessenger* messenger, FlValue* message, |
| 23 | + gpointer user_data) { |
| 24 | + gboolean* called = static_cast<gboolean*>(user_data); |
| 25 | + *called = TRUE; |
| 26 | + |
| 27 | + EXPECT_NE(message, nullptr); |
| 28 | + EXPECT_EQ(fl_value_get_type(message), FL_VALUE_TYPE_STRING); |
| 29 | + EXPECT_STREQ(fl_value_get_string(message), "Marco!"); |
| 30 | + |
| 31 | + // No response. |
| 32 | + return static_cast<FlValue*>(nullptr); |
| 33 | + }, |
| 34 | + &called); |
24 | 35 |
|
25 | | - g_autoptr(FlEngine) engine = make_mock_engine(); |
26 | | - FlutterEngineProcTable* embedder_api = fl_engine_get_embedder_api(engine); |
27 | | - |
28 | | - bool called = false; |
29 | | - FlutterEngineSendPlatformMessageFnPtr old_handler = |
30 | | - embedder_api->SendPlatformMessage; |
31 | | - embedder_api->SendPlatformMessage = MOCK_ENGINE_PROC( |
32 | | - SendPlatformMessage, |
33 | | - ([&called, old_handler](auto engine, |
34 | | - const FlutterPlatformMessage* message) { |
35 | | - if (strcmp(message->channel, "test") != 0) { |
36 | | - return old_handler(engine, message); |
37 | | - } |
38 | | - |
39 | | - called = true; |
40 | | - EXPECT_EQ(message->response_handle, nullptr); |
41 | | - |
42 | | - g_autoptr(GBytes) message_bytes = |
43 | | - g_bytes_new(message->message, message->message_size); |
44 | | - g_autoptr(FlStandardMessageCodec) codec = |
45 | | - fl_standard_message_codec_new(); |
46 | | - g_autoptr(FlValue) message_value = fl_message_codec_decode_message( |
47 | | - FL_MESSAGE_CODEC(codec), message_bytes, nullptr); |
48 | | - EXPECT_EQ(fl_value_get_type(message_value), FL_VALUE_TYPE_STRING); |
49 | | - EXPECT_STREQ(fl_value_get_string(message_value), "Hello World!"); |
50 | | - |
51 | | - return kSuccess; |
52 | | - })); |
53 | | - |
54 | | - g_autoptr(FlBinaryMessenger) messenger = fl_binary_messenger_new(engine); |
55 | 36 | g_autoptr(FlStandardMessageCodec) codec = fl_standard_message_codec_new(); |
56 | | - g_autoptr(FlBasicMessageChannel) channel = |
57 | | - fl_basic_message_channel_new(messenger, "test", FL_MESSAGE_CODEC(codec)); |
58 | | - g_autoptr(FlValue) message = fl_value_new_string("Hello World!"); |
59 | | - fl_basic_message_channel_send(channel, message, nullptr, nullptr, loop); |
| 37 | + g_autoptr(FlBasicMessageChannel) channel = fl_basic_message_channel_new( |
| 38 | + FL_BINARY_MESSENGER(messenger), "test", FL_MESSAGE_CODEC(codec)); |
| 39 | + g_autoptr(FlValue) message = fl_value_new_string("Marco!"); |
| 40 | + fl_basic_message_channel_send(channel, message, nullptr, nullptr, nullptr); |
60 | 41 |
|
61 | 42 | EXPECT_TRUE(called); |
62 | 43 | } |
63 | 44 | // NOLINTEND(clang-analyzer-core.StackAddressEscape) |
64 | 45 |
|
65 | | -// Called when the message response is received in the SendMessageWithResponse |
66 | | -// test. |
67 | | -static void echo_response_cb(GObject* object, |
68 | | - GAsyncResult* result, |
69 | | - gpointer user_data) { |
70 | | - g_autoptr(GError) error = nullptr; |
71 | | - g_autoptr(FlValue) message = fl_basic_message_channel_send_finish( |
72 | | - FL_BASIC_MESSAGE_CHANNEL(object), result, &error); |
73 | | - EXPECT_NE(message, nullptr); |
74 | | - EXPECT_EQ(error, nullptr); |
75 | | - |
76 | | - EXPECT_EQ(fl_value_get_type(message), FL_VALUE_TYPE_STRING); |
77 | | - EXPECT_STREQ(fl_value_get_string(message), "Hello World!"); |
78 | | - |
79 | | - g_main_loop_quit(static_cast<GMainLoop*>(user_data)); |
80 | | -} |
81 | | - |
82 | 46 | // Checks sending a message with a response works. |
83 | 47 | TEST(FlBasicMessageChannelTest, SendMessageWithResponse) { |
84 | 48 | g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0); |
85 | 49 |
|
86 | | - g_autoptr(FlEngine) engine = make_mock_engine(); |
87 | | - g_autoptr(FlBinaryMessenger) messenger = fl_binary_messenger_new(engine); |
| 50 | + g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new(); |
| 51 | + fl_mock_binary_messenger_set_standard_message_channel( |
| 52 | + messenger, "test", |
| 53 | + [](FlMockBinaryMessenger* messenger, FlValue* message, |
| 54 | + gpointer user_data) { |
| 55 | + EXPECT_NE(message, nullptr); |
| 56 | + EXPECT_EQ(fl_value_get_type(message), FL_VALUE_TYPE_STRING); |
| 57 | + EXPECT_STREQ(fl_value_get_string(message), "Marco!"); |
| 58 | + |
| 59 | + return fl_value_new_string("Polo!"); |
| 60 | + }, |
| 61 | + nullptr); |
| 62 | + |
88 | 63 | g_autoptr(FlStandardMessageCodec) codec = fl_standard_message_codec_new(); |
89 | 64 | g_autoptr(FlBasicMessageChannel) channel = fl_basic_message_channel_new( |
90 | | - messenger, "test/echo", FL_MESSAGE_CODEC(codec)); |
91 | | - g_autoptr(FlValue) message = fl_value_new_string("Hello World!"); |
92 | | - fl_basic_message_channel_send(channel, message, nullptr, echo_response_cb, |
93 | | - loop); |
| 65 | + FL_BINARY_MESSENGER(messenger), "test", FL_MESSAGE_CODEC(codec)); |
| 66 | + g_autoptr(FlValue) message = fl_value_new_string("Marco!"); |
| 67 | + fl_basic_message_channel_send( |
| 68 | + channel, message, nullptr, |
| 69 | + [](GObject* object, GAsyncResult* result, gpointer user_data) { |
| 70 | + g_autoptr(GError) error = nullptr; |
| 71 | + g_autoptr(FlValue) message = fl_basic_message_channel_send_finish( |
| 72 | + FL_BASIC_MESSAGE_CHANNEL(object), result, &error); |
| 73 | + EXPECT_NE(message, nullptr); |
| 74 | + EXPECT_EQ(error, nullptr); |
| 75 | + |
| 76 | + EXPECT_EQ(fl_value_get_type(message), FL_VALUE_TYPE_STRING); |
| 77 | + EXPECT_STREQ(fl_value_get_string(message), "Polo!"); |
| 78 | + |
| 79 | + g_main_loop_quit(static_cast<GMainLoop*>(user_data)); |
| 80 | + }, |
| 81 | + loop); |
94 | 82 |
|
95 | | - // Blocks here until echo_response_cb is called. |
96 | 83 | g_main_loop_run(loop); |
97 | 84 | } |
98 | 85 |
|
99 | | -// Called when the message response is received in the SendFailure test. |
100 | | -static void failure_response_cb(GObject* object, |
101 | | - GAsyncResult* result, |
102 | | - gpointer user_data) { |
103 | | - g_autoptr(GError) error = nullptr; |
104 | | - g_autoptr(FlValue) message = fl_basic_message_channel_send_finish( |
105 | | - FL_BASIC_MESSAGE_CHANNEL(object), result, &error); |
106 | | - EXPECT_EQ(message, nullptr); |
107 | | - EXPECT_NE(error, nullptr); |
108 | | - |
109 | | - g_main_loop_quit(static_cast<GMainLoop*>(user_data)); |
110 | | -} |
111 | | - |
112 | 86 | // Checks the engine reporting a send failure is handled. |
113 | 87 | TEST(FlBasicMessageChannelTest, SendFailure) { |
114 | 88 | g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0); |
115 | 89 |
|
116 | | - g_autoptr(FlEngine) engine = make_mock_engine(); |
117 | | - g_autoptr(FlBinaryMessenger) messenger = fl_binary_messenger_new(engine); |
| 90 | + g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new(); |
| 91 | + fl_mock_binary_messenger_set_error_channel(messenger, "test", 42, "Error"); |
| 92 | + |
118 | 93 | g_autoptr(FlStandardMessageCodec) codec = fl_standard_message_codec_new(); |
119 | 94 | g_autoptr(FlBasicMessageChannel) channel = fl_basic_message_channel_new( |
120 | | - messenger, "test/failure", FL_MESSAGE_CODEC(codec)); |
| 95 | + FL_BINARY_MESSENGER(messenger), "test", FL_MESSAGE_CODEC(codec)); |
121 | 96 | g_autoptr(FlValue) message = fl_value_new_string("Hello World!"); |
122 | | - fl_basic_message_channel_send(channel, message, nullptr, failure_response_cb, |
123 | | - loop); |
| 97 | + fl_basic_message_channel_send( |
| 98 | + channel, message, nullptr, |
| 99 | + [](GObject* object, GAsyncResult* result, gpointer user_data) { |
| 100 | + g_autoptr(GError) error = nullptr; |
| 101 | + g_autoptr(FlValue) message = fl_basic_message_channel_send_finish( |
| 102 | + FL_BASIC_MESSAGE_CHANNEL(object), result, &error); |
| 103 | + EXPECT_EQ(message, nullptr); |
| 104 | + EXPECT_NE(error, nullptr); |
| 105 | + EXPECT_EQ(error->code, 42); |
| 106 | + EXPECT_STREQ(error->message, "Error"); |
| 107 | + |
| 108 | + g_main_loop_quit(static_cast<GMainLoop*>(user_data)); |
| 109 | + }, |
| 110 | + loop); |
124 | 111 |
|
125 | | - // Blocks here until failure_response_cb is called. |
126 | 112 | g_main_loop_run(loop); |
127 | 113 | } |
128 | 114 |
|
129 | | -// Called when a message is received from the engine in the ReceiveMessage test. |
130 | | -static void message_cb(FlBasicMessageChannel* channel, |
131 | | - FlValue* message, |
132 | | - FlBasicMessageChannelResponseHandle* response_handle, |
133 | | - gpointer user_data) { |
134 | | - EXPECT_NE(message, nullptr); |
135 | | - EXPECT_EQ(fl_value_get_type(message), FL_VALUE_TYPE_STRING); |
136 | | - EXPECT_STREQ(fl_value_get_string(message), "Marco!"); |
137 | | - |
138 | | - g_autoptr(GError) error = nullptr; |
139 | | - g_autoptr(FlValue) response = fl_value_new_string("Polo!"); |
140 | | - EXPECT_TRUE(fl_basic_message_channel_respond(channel, response_handle, |
141 | | - response, &error)); |
142 | | - EXPECT_EQ(error, nullptr); |
143 | | -} |
144 | | - |
145 | | -// Called when a the test engine notifies us what response we sent in the |
146 | | -// ReceiveMessage test. |
147 | | -static void response_cb(FlBasicMessageChannel* channel, |
148 | | - FlValue* message, |
149 | | - FlBasicMessageChannelResponseHandle* response_handle, |
150 | | - gpointer user_data) { |
151 | | - EXPECT_NE(message, nullptr); |
152 | | - EXPECT_EQ(fl_value_get_type(message), FL_VALUE_TYPE_STRING); |
153 | | - EXPECT_STREQ(fl_value_get_string(message), "Polo!"); |
154 | | - |
155 | | - fl_basic_message_channel_respond(channel, response_handle, nullptr, nullptr); |
156 | | - |
157 | | - g_main_loop_quit(static_cast<GMainLoop*>(user_data)); |
158 | | -} |
159 | | - |
160 | 115 | // Checks the shell able to receive and respond to messages from the engine. |
161 | 116 | TEST(FlBasicMessageChannelTest, ReceiveMessage) { |
162 | | - g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0); |
163 | | - |
164 | | - g_autoptr(FlEngine) engine = make_mock_engine(); |
165 | | - g_autoptr(FlBinaryMessenger) messenger = fl_binary_messenger_new(engine); |
| 117 | + g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new(); |
166 | 118 |
|
167 | 119 | // Listen for messages from the engine. |
168 | 120 | g_autoptr(FlStandardMessageCodec) codec = fl_standard_message_codec_new(); |
169 | 121 | g_autoptr(FlBasicMessageChannel) messages_channel = |
170 | | - fl_basic_message_channel_new(messenger, "test/messages", |
171 | | - FL_MESSAGE_CODEC(codec)); |
172 | | - fl_basic_message_channel_set_message_handler(messages_channel, message_cb, |
173 | | - nullptr, nullptr); |
174 | | - |
175 | | - // Listen for response from the engine. |
176 | | - g_autoptr(FlBasicMessageChannel) responses_channel = |
177 | | - fl_basic_message_channel_new(messenger, "test/responses", |
178 | | - FL_MESSAGE_CODEC(codec)); |
179 | | - fl_basic_message_channel_set_message_handler(responses_channel, response_cb, |
180 | | - loop, nullptr); |
181 | | - |
182 | | - // Triggger the engine to send a message. |
183 | | - g_autoptr(FlBasicMessageChannel) control_channel = |
184 | | - fl_basic_message_channel_new(messenger, "test/send-message", |
| 122 | + fl_basic_message_channel_new(FL_BINARY_MESSENGER(messenger), "test", |
185 | 123 | FL_MESSAGE_CODEC(codec)); |
| 124 | + fl_basic_message_channel_set_message_handler( |
| 125 | + messages_channel, |
| 126 | + [](FlBasicMessageChannel* channel, FlValue* message, |
| 127 | + FlBasicMessageChannelResponseHandle* response_handle, |
| 128 | + gpointer user_data) { |
| 129 | + EXPECT_NE(message, nullptr); |
| 130 | + EXPECT_EQ(fl_value_get_type(message), FL_VALUE_TYPE_STRING); |
| 131 | + EXPECT_STREQ(fl_value_get_string(message), "Marco!"); |
| 132 | + |
| 133 | + g_autoptr(GError) error = nullptr; |
| 134 | + g_autoptr(FlValue) response = fl_value_new_string("Polo!"); |
| 135 | + EXPECT_TRUE(fl_basic_message_channel_respond(channel, response_handle, |
| 136 | + response, &error)); |
| 137 | + EXPECT_EQ(error, nullptr); |
| 138 | + }, |
| 139 | + nullptr, nullptr); |
| 140 | + |
| 141 | + // Trigger the engine to send a message. |
186 | 142 | g_autoptr(FlValue) message = fl_value_new_string("Marco!"); |
187 | | - fl_basic_message_channel_send(control_channel, message, nullptr, nullptr, |
188 | | - nullptr); |
| 143 | + gboolean called = FALSE; |
| 144 | + fl_mock_binary_messenger_send_standard_message( |
| 145 | + messenger, "test", message, |
| 146 | + [](FlMockBinaryMessenger* messenger, FlValue* response, |
| 147 | + gpointer user_data) { |
| 148 | + gboolean* called = static_cast<gboolean*>(user_data); |
| 149 | + *called = TRUE; |
| 150 | + |
| 151 | + EXPECT_NE(response, nullptr); |
| 152 | + EXPECT_EQ(fl_value_get_type(response), FL_VALUE_TYPE_STRING); |
| 153 | + EXPECT_STREQ(fl_value_get_string(response), "Polo!"); |
| 154 | + }, |
| 155 | + &called); |
189 | 156 |
|
190 | | - // Blocks here until response_cb is called. |
191 | | - g_main_loop_run(loop); |
192 | | -} |
193 | | - |
194 | | -// Called when the message response is received in the |
195 | | -// SendNullMessageWithResponse test. |
196 | | -static void null_message_response_cb(GObject* object, |
197 | | - GAsyncResult* result, |
198 | | - gpointer user_data) { |
199 | | - g_autoptr(GError) error = nullptr; |
200 | | - g_autoptr(FlValue) message = fl_basic_message_channel_send_finish( |
201 | | - FL_BASIC_MESSAGE_CHANNEL(object), result, &error); |
202 | | - EXPECT_NE(message, nullptr); |
203 | | - EXPECT_EQ(error, nullptr); |
204 | | - |
205 | | - EXPECT_EQ(fl_value_get_type(message), FL_VALUE_TYPE_NULL); |
206 | | - |
207 | | - g_main_loop_quit(static_cast<GMainLoop*>(user_data)); |
| 157 | + EXPECT_TRUE(called); |
208 | 158 | } |
209 | 159 |
|
210 | 160 | // Checks sending a null message with a response works. |
211 | 161 | TEST(FlBasicMessageChannelTest, SendNullMessageWithResponse) { |
212 | 162 | g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0); |
213 | 163 |
|
214 | | - g_autoptr(FlEngine) engine = make_mock_engine(); |
215 | | - g_autoptr(FlBinaryMessenger) messenger = fl_binary_messenger_new(engine); |
| 164 | + g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new(); |
| 165 | + fl_mock_binary_messenger_set_standard_message_channel( |
| 166 | + messenger, "test", |
| 167 | + [](FlMockBinaryMessenger* messenger, FlValue* message, |
| 168 | + gpointer user_data) { return fl_value_new_null(); }, |
| 169 | + nullptr); |
| 170 | + |
216 | 171 | g_autoptr(FlStandardMessageCodec) codec = fl_standard_message_codec_new(); |
217 | 172 | g_autoptr(FlBasicMessageChannel) channel = fl_basic_message_channel_new( |
218 | | - messenger, "test/echo", FL_MESSAGE_CODEC(codec)); |
219 | | - fl_basic_message_channel_send(channel, nullptr, nullptr, |
220 | | - null_message_response_cb, loop); |
| 173 | + FL_BINARY_MESSENGER(messenger), "test", FL_MESSAGE_CODEC(codec)); |
| 174 | + fl_basic_message_channel_send( |
| 175 | + channel, nullptr, nullptr, |
| 176 | + [](GObject* object, GAsyncResult* result, gpointer user_data) { |
| 177 | + g_autoptr(GError) error = nullptr; |
| 178 | + g_autoptr(FlValue) message = fl_basic_message_channel_send_finish( |
| 179 | + FL_BASIC_MESSAGE_CHANNEL(object), result, &error); |
| 180 | + EXPECT_NE(message, nullptr); |
| 181 | + EXPECT_EQ(error, nullptr); |
| 182 | + |
| 183 | + EXPECT_EQ(fl_value_get_type(message), FL_VALUE_TYPE_NULL); |
| 184 | + |
| 185 | + g_main_loop_quit(static_cast<GMainLoop*>(user_data)); |
| 186 | + }, |
| 187 | + loop); |
221 | 188 |
|
222 | | - // Blocks here until null_message_response_cb is called. |
223 | 189 | g_main_loop_run(loop); |
224 | 190 | } |
225 | 191 |
|
226 | | -// Called when the message response is received in the CustomType test. |
227 | | -static void custom_type_response_cb(GObject* object, |
228 | | - GAsyncResult* result, |
229 | | - gpointer user_data) { |
230 | | - g_autoptr(GError) error = nullptr; |
231 | | - g_autoptr(FlValue) message = fl_basic_message_channel_send_finish( |
232 | | - FL_BASIC_MESSAGE_CHANNEL(object), result, &error); |
233 | | - EXPECT_EQ(message, nullptr); |
234 | | - EXPECT_NE(error, nullptr); |
235 | | - EXPECT_STREQ(error->message, "Custom value not implemented"); |
236 | | - |
237 | | - g_main_loop_quit(static_cast<GMainLoop*>(user_data)); |
238 | | -} |
239 | | - |
240 | 192 | // Checks sending a message with a custom type generates an error. |
241 | 193 | TEST(FlBasicMessageChannelTest, CustomType) { |
242 | 194 | g_autoptr(GMainLoop) loop = g_main_loop_new(nullptr, 0); |
243 | 195 |
|
244 | | - // Attempt to send an integer with the string codec. |
245 | | - g_autoptr(FlEngine) engine = make_mock_engine(); |
246 | | - g_autoptr(FlBinaryMessenger) messenger = fl_binary_messenger_new(engine); |
| 196 | + g_autoptr(FlMockBinaryMessenger) messenger = fl_mock_binary_messenger_new(); |
| 197 | + fl_mock_binary_messenger_set_standard_message_channel( |
| 198 | + messenger, "test", |
| 199 | + [](FlMockBinaryMessenger* messenger, FlValue* message, |
| 200 | + gpointer user_data) { return fl_value_new_null(); }, |
| 201 | + nullptr); |
| 202 | + |
247 | 203 | g_autoptr(FlStandardMessageCodec) codec = fl_standard_message_codec_new(); |
248 | 204 | g_autoptr(FlBasicMessageChannel) channel = fl_basic_message_channel_new( |
249 | | - messenger, "test/echo", FL_MESSAGE_CODEC(codec)); |
| 205 | + FL_BINARY_MESSENGER(messenger), "test", FL_MESSAGE_CODEC(codec)); |
250 | 206 | g_autoptr(FlValue) message = fl_value_new_custom(42, nullptr, nullptr); |
251 | | - fl_basic_message_channel_send(channel, message, nullptr, |
252 | | - custom_type_response_cb, loop); |
| 207 | + fl_basic_message_channel_send( |
| 208 | + channel, message, nullptr, |
| 209 | + [](GObject* object, GAsyncResult* result, gpointer user_data) { |
| 210 | + g_autoptr(GError) error = nullptr; |
| 211 | + g_autoptr(FlValue) message = fl_basic_message_channel_send_finish( |
| 212 | + FL_BASIC_MESSAGE_CHANNEL(object), result, &error); |
| 213 | + EXPECT_EQ(message, nullptr); |
| 214 | + EXPECT_NE(error, nullptr); |
| 215 | + EXPECT_STREQ(error->message, "Custom value not implemented"); |
| 216 | + |
| 217 | + g_main_loop_quit(static_cast<GMainLoop*>(user_data)); |
| 218 | + }, |
| 219 | + loop); |
253 | 220 |
|
254 | | - // Blocks here until custom_type_response_cb is called. |
255 | 221 | g_main_loop_run(loop); |
256 | 222 | } |
0 commit comments