Flutter Engine
fl_method_codec_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 #include "flutter/shell/platform/linux/public/flutter_linux/fl_method_codec.h"
6 
7 #include <cstring>
8 
9 #include "flutter/shell/platform/linux/fl_method_codec_private.h"
10 #include "flutter/shell/platform/linux/public/flutter_linux/fl_message_codec.h"
11 #include "gtest/gtest.h"
12 
13 G_DECLARE_FINAL_TYPE(FlTestMethodCodec,
14  fl_test_method_codec,
15  FL,
16  TEST_METHOD_CODEC,
17  FlMethodCodec)
18 
19 // Implement the FlMethodCodec API for the following tests to check it works as
20 // expected.
21 struct _FlTestMethodCodec {
22  FlMethodCodec parent_instance;
23 };
24 
25 G_DEFINE_TYPE(FlTestMethodCodec,
26  fl_test_method_codec,
28 
29 // Helper function to convert binary data to text.
30 static gchar* message_to_text(GBytes* message) {
31  size_t data_length;
32  const gchar* data =
33  static_cast<const gchar*>(g_bytes_get_data(message, &data_length));
34  return g_strndup(data, data_length);
35 }
36 
37 // Helper function to convert text to binary data.
38 static GBytes* text_to_message(const gchar* text) {
39  return g_bytes_new(text, strlen(text));
40 }
41 
42 // Implements FlMethodCodec::encode_method_call.
43 static GBytes* fl_test_codec_encode_method_call(FlMethodCodec* codec,
44  const gchar* name,
45  FlValue* args,
46  GError** error) {
47  EXPECT_TRUE(FL_IS_TEST_METHOD_CODEC(codec));
48 
49  g_autofree gchar* text = nullptr;
50  if (args == nullptr || fl_value_get_type(args) == FL_VALUE_TYPE_NULL) {
51  text = g_strdup_printf("%s()", name);
52  } else if (fl_value_get_type(args) == FL_VALUE_TYPE_INT) {
53  text = g_strdup_printf("%s(%" G_GINT64_FORMAT ")", name,
54  fl_value_get_int(args));
55  } else {
57  "ERROR");
58  return nullptr;
59  }
60 
61  return text_to_message(text);
62 }
63 
64 // Implements FlMethodCodec::decode_method_call.
65 static gboolean fl_test_codec_decode_method_call(FlMethodCodec* codec,
66  GBytes* message,
67  gchar** name,
68  FlValue** args,
69  GError** error) {
70  EXPECT_TRUE(FL_IS_TEST_METHOD_CODEC(codec));
71 
72  g_autofree gchar* m = message_to_text(message);
73 
74  if (strcmp(m, "error") == 0) {
76  "ERROR");
77  return FALSE;
78  } else {
79  *name = g_strdup(m);
80  *args = fl_value_new_null();
81  return TRUE;
82  }
83 }
84 
85 // Implements FlMethodCodec::encode_success_envelope.
86 static GBytes* fl_test_codec_encode_success_envelope(FlMethodCodec* codec,
87  FlValue* result,
88  GError** error) {
89  EXPECT_TRUE(FL_IS_TEST_METHOD_CODEC(codec));
90 
91  g_autofree gchar* text = nullptr;
92  if (result == nullptr || fl_value_get_type(result) == FL_VALUE_TYPE_NULL) {
93  text = g_strdup("(null)");
94  } else if (fl_value_get_type(result) == FL_VALUE_TYPE_INT) {
95  text = g_strdup_printf("%" G_GINT64_FORMAT, fl_value_get_int(result));
96  } else {
98  "ERROR");
99  return nullptr;
100  }
101 
102  return text_to_message(text);
103 }
104 
105 // Implements FlMethodCodec::encode_error_envelope.
106 static GBytes* fl_test_codec_encode_error_envelope(FlMethodCodec* codec,
107  const gchar* code,
108  const gchar* message,
109  FlValue* details,
110  GError** error) {
111  EXPECT_TRUE(FL_IS_TEST_METHOD_CODEC(codec));
112 
113  if (details != nullptr && fl_value_get_type(details) != FL_VALUE_TYPE_INT) {
115  "ERROR");
116  return nullptr;
117  }
118 
119  g_autofree gchar* text = nullptr;
120  if (message == nullptr) {
121  if (details == nullptr ||
123  text = g_strdup_printf("Error_%s()", code);
124  } else {
125  text = g_strdup_printf("Error_%s(%" G_GINT64_FORMAT ")", code,
126  fl_value_get_int(details));
127  }
128  } else {
129  if (details == nullptr ||
131  text = g_strdup_printf("Error_%s(%s)", code, message);
132  } else {
133  text = g_strdup_printf("Error_%s(%s,%" G_GINT64_FORMAT ")", code, message,
134  fl_value_get_int(details));
135  }
136  }
137 
138  return text_to_message(text);
139 }
140 
141 // Implements FlMethodCodec::decode_response.
142 static FlMethodResponse* fl_test_codec_decode_response(FlMethodCodec* codec,
143  GBytes* message,
144  GError** error) {
145  EXPECT_TRUE(FL_IS_TEST_METHOD_CODEC(codec));
146 
147  g_autofree gchar* m = message_to_text(message);
148  if (strcmp(m, "codec-error") == 0) {
150  "ERROR");
151  return nullptr;
152  } else if (strcmp(m, "error") == 0) {
153  g_autoptr(FlValue) details = fl_value_new_int(42);
154  return FL_METHOD_RESPONSE(
155  fl_method_error_response_new("code", "message", details));
156  } else {
157  g_autoptr(FlValue) result = fl_value_new_string(m);
158  return FL_METHOD_RESPONSE(fl_method_success_response_new(result));
159  }
160 }
161 
162 static void fl_test_method_codec_class_init(FlTestMethodCodecClass* klass) {
163  FL_METHOD_CODEC_CLASS(klass)->encode_method_call =
165  FL_METHOD_CODEC_CLASS(klass)->decode_method_call =
167  FL_METHOD_CODEC_CLASS(klass)->encode_success_envelope =
169  FL_METHOD_CODEC_CLASS(klass)->encode_error_envelope =
171  FL_METHOD_CODEC_CLASS(klass)->decode_response = fl_test_codec_decode_response;
172 }
173 
174 static void fl_test_method_codec_init(FlTestMethodCodec* self) {}
175 
176 static FlTestMethodCodec* fl_test_method_codec_new() {
177  return FL_TEST_METHOD_CODEC(
178  g_object_new(fl_test_method_codec_get_type(), nullptr));
179 }
180 
181 TEST(FlMethodCodecTest, EncodeMethodCall) {
182  g_autoptr(FlTestMethodCodec) codec = fl_test_method_codec_new();
183 
184  g_autoptr(GError) error = nullptr;
185  g_autoptr(GBytes) message = fl_method_codec_encode_method_call(
186  FL_METHOD_CODEC(codec), "foo", nullptr, &error);
187  EXPECT_EQ(error, nullptr);
188  EXPECT_NE(message, nullptr);
189 
190  g_autofree gchar* message_text = message_to_text(message);
191  EXPECT_STREQ(message_text, "foo()");
192 }
193 
194 TEST(FlMethodCodecTest, EncodeMethodCallEmptyName) {
195  g_autoptr(FlTestMethodCodec) codec = fl_test_method_codec_new();
196 
197  g_autoptr(GError) error = nullptr;
198  g_autoptr(GBytes) message = fl_method_codec_encode_method_call(
199  FL_METHOD_CODEC(codec), "", nullptr, &error);
200  EXPECT_EQ(error, nullptr);
201  EXPECT_NE(message, nullptr);
202 
203  g_autofree gchar* message_text = message_to_text(message);
204  EXPECT_STREQ(message_text, "()");
205 }
206 
207 TEST(FlMethodCodecTest, EncodeMethodCallArgs) {
208  g_autoptr(FlTestMethodCodec) codec = fl_test_method_codec_new();
209 
210  g_autoptr(FlValue) args = fl_value_new_int(42);
211  g_autoptr(GError) error = nullptr;
212  g_autoptr(GBytes) message = fl_method_codec_encode_method_call(
213  FL_METHOD_CODEC(codec), "foo", args, &error);
214  EXPECT_EQ(error, nullptr);
215  EXPECT_NE(message, nullptr);
216 
217  g_autofree gchar* message_text = message_to_text(message);
218  EXPECT_STREQ(message_text, "foo(42)");
219 }
220 
221 TEST(FlMethodCodecTest, EncodeMethodCallError) {
222  g_autoptr(FlTestMethodCodec) codec = fl_test_method_codec_new();
223 
224  g_autoptr(FlValue) args = fl_value_new_bool(FALSE);
225  g_autoptr(GError) error = nullptr;
226  g_autoptr(GBytes) message = fl_method_codec_encode_method_call(
227  FL_METHOD_CODEC(codec), "foo", args, &error);
228  EXPECT_EQ(message, nullptr);
229  EXPECT_TRUE(g_error_matches(error, FL_MESSAGE_CODEC_ERROR,
231 }
232 
233 TEST(FlMethodCodecTest, DecodeMethodCall) {
234  g_autoptr(FlTestMethodCodec) codec = fl_test_method_codec_new();
235 
236  g_autoptr(GBytes) message = text_to_message("foo");
237 
238  g_autofree gchar* name = nullptr;
239  g_autoptr(FlValue) args = nullptr;
240  g_autoptr(GError) error = nullptr;
241  gboolean result = fl_method_codec_decode_method_call(
242  FL_METHOD_CODEC(codec), message, &name, &args, &error);
243  EXPECT_EQ(error, nullptr);
244  EXPECT_TRUE(result);
245 
246  EXPECT_STREQ(name, "foo");
248 }
249 
250 TEST(FlMethodCodecTest, EncodeSuccessEnvelope) {
251  g_autoptr(FlTestMethodCodec) codec = fl_test_method_codec_new();
252 
253  g_autoptr(FlValue) result = fl_value_new_int(42);
254  g_autoptr(GError) error = nullptr;
255  g_autoptr(GBytes) message = fl_method_codec_encode_success_envelope(
256  FL_METHOD_CODEC(codec), result, &error);
257  EXPECT_EQ(error, nullptr);
258  EXPECT_NE(message, nullptr);
259 
260  g_autofree gchar* message_text = message_to_text(message);
261  EXPECT_STREQ(message_text, "42");
262 }
263 
264 TEST(FlMethodCodecTest, EncodeSuccessEnvelopeEmpty) {
265  g_autoptr(FlTestMethodCodec) codec = fl_test_method_codec_new();
266 
267  g_autoptr(GError) error = nullptr;
268  g_autoptr(GBytes) message = fl_method_codec_encode_success_envelope(
269  FL_METHOD_CODEC(codec), nullptr, &error);
270  EXPECT_EQ(error, nullptr);
271  EXPECT_NE(message, nullptr);
272 
273  g_autofree gchar* message_text = message_to_text(message);
274  EXPECT_STREQ(message_text, "(null)");
275 }
276 
277 TEST(FlMethodCodecTest, EncodeSuccessEnvelopeError) {
278  g_autoptr(FlTestMethodCodec) codec = fl_test_method_codec_new();
279 
280  g_autoptr(FlValue) result = fl_value_new_string("X");
281  g_autoptr(GError) error = nullptr;
282  g_autoptr(GBytes) message = fl_method_codec_encode_success_envelope(
283  FL_METHOD_CODEC(codec), result, &error);
284  EXPECT_EQ(message, nullptr);
285  EXPECT_TRUE(g_error_matches(error, FL_MESSAGE_CODEC_ERROR,
287 }
288 
289 TEST(FlMethodCodecTest, EncodeErrorEnvelopeNoMessageOrDetails) {
290  g_autoptr(FlTestMethodCodec) codec = fl_test_method_codec_new();
291 
292  g_autoptr(GError) error = nullptr;
293  g_autoptr(GBytes) message = fl_method_codec_encode_error_envelope(
294  FL_METHOD_CODEC(codec), "code", nullptr, nullptr, &error);
295  EXPECT_EQ(error, nullptr);
296  EXPECT_NE(message, nullptr);
297 
298  g_autofree gchar* message_text = message_to_text(message);
299  EXPECT_STREQ(message_text, "Error_code()");
300 }
301 
302 TEST(FlMethodCodecTest, EncodeErrorEnvelopeMessage) {
303  g_autoptr(FlTestMethodCodec) codec = fl_test_method_codec_new();
304 
305  g_autoptr(GError) error = nullptr;
306  g_autoptr(GBytes) message = fl_method_codec_encode_error_envelope(
307  FL_METHOD_CODEC(codec), "code", "message", nullptr, &error);
308  EXPECT_EQ(error, nullptr);
309  EXPECT_NE(message, nullptr);
310 
311  g_autofree gchar* message_text = message_to_text(message);
312  EXPECT_STREQ(message_text, "Error_code(message)");
313 }
314 
315 TEST(FlMethodCodecTest, EncodeErrorEnvelopeDetails) {
316  g_autoptr(FlTestMethodCodec) codec = fl_test_method_codec_new();
317 
318  g_autoptr(FlValue) details = fl_value_new_int(42);
319  g_autoptr(GError) error = nullptr;
320  g_autoptr(GBytes) message = fl_method_codec_encode_error_envelope(
321  FL_METHOD_CODEC(codec), "code", nullptr, details, &error);
322  EXPECT_EQ(error, nullptr);
323  EXPECT_NE(message, nullptr);
324 
325  g_autofree gchar* message_text = message_to_text(message);
326  EXPECT_STREQ(message_text, "Error_code(42)");
327 }
328 
329 TEST(FlMethodCodecTest, EncodeErrorEnvelopeMessageAndDetails) {
330  g_autoptr(FlTestMethodCodec) codec = fl_test_method_codec_new();
331 
332  g_autoptr(FlValue) details = fl_value_new_int(42);
333  g_autoptr(GError) error = nullptr;
334  g_autoptr(GBytes) message = fl_method_codec_encode_error_envelope(
335  FL_METHOD_CODEC(codec), "code", "message", details, &error);
336  EXPECT_EQ(error, nullptr);
337  EXPECT_NE(message, nullptr);
338 
339  g_autofree gchar* message_text = message_to_text(message);
340  EXPECT_STREQ(message_text, "Error_code(message,42)");
341 }
342 
343 TEST(FlMethodCodecTest, DecodeResponseSuccess) {
344  g_autoptr(FlTestMethodCodec) codec = fl_test_method_codec_new();
345 
346  g_autoptr(GBytes) message = text_to_message("echo");
347 
348  g_autoptr(GError) error = nullptr;
349  g_autoptr(FlMethodResponse) response =
350  fl_method_codec_decode_response(FL_METHOD_CODEC(codec), message, &error);
351  EXPECT_EQ(error, nullptr);
352  EXPECT_NE(response, nullptr);
353  ASSERT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response));
355  FL_METHOD_SUCCESS_RESPONSE(response));
356  ASSERT_NE(result, nullptr);
357  ASSERT_EQ(fl_value_get_type(result), FL_VALUE_TYPE_STRING);
358  EXPECT_STREQ(fl_value_get_string(result), "echo");
359 }
360 
361 TEST(FlMethodCodecTest, DecodeResponseNotImplemented) {
362  g_autoptr(FlTestMethodCodec) codec = fl_test_method_codec_new();
363 
364  g_autoptr(GBytes) message = g_bytes_new(nullptr, 0);
365 
366  g_autoptr(GError) error = nullptr;
367  g_autoptr(FlMethodResponse) response =
368  fl_method_codec_decode_response(FL_METHOD_CODEC(codec), message, &error);
369  EXPECT_EQ(error, nullptr);
370  EXPECT_NE(response, nullptr);
371  ASSERT_TRUE(FL_IS_METHOD_NOT_IMPLEMENTED_RESPONSE(response));
372 }
373 
374 TEST(FlMethodCodecTest, DecodeResponseCodecError) {
375  g_autoptr(FlTestMethodCodec) codec = fl_test_method_codec_new();
376 
377  g_autoptr(GBytes) message = text_to_message("codec-error");
378 
379  g_autoptr(GError) error = nullptr;
380  g_autoptr(FlMethodResponse) response =
381  fl_method_codec_decode_response(FL_METHOD_CODEC(codec), message, &error);
382  EXPECT_TRUE(g_error_matches(error, FL_MESSAGE_CODEC_ERROR,
384  EXPECT_EQ(response, nullptr);
385 }
386 
387 TEST(FlMethodCodecTest, DecodeResponseError) {
388  g_autoptr(FlTestMethodCodec) codec = fl_test_method_codec_new();
389 
390  g_autoptr(GBytes) message = text_to_message("error");
391 
392  g_autoptr(GError) error = nullptr;
393  g_autoptr(FlMethodResponse) response =
394  fl_method_codec_decode_response(FL_METHOD_CODEC(codec), message, &error);
395  EXPECT_EQ(error, nullptr);
396  EXPECT_NE(response, nullptr);
397  ASSERT_TRUE(FL_METHOD_ERROR_RESPONSE(response));
398  EXPECT_STREQ(
399  fl_method_error_response_get_code(FL_METHOD_ERROR_RESPONSE(response)),
400  "code");
401  EXPECT_STREQ(
402  fl_method_error_response_get_message(FL_METHOD_ERROR_RESPONSE(response)),
403  "message");
404  FlValue* details =
405  fl_method_error_response_get_details(FL_METHOD_ERROR_RESPONSE(response));
406  ASSERT_NE(details, nullptr);
407  ASSERT_EQ(fl_value_get_type(details), FL_VALUE_TYPE_INT);
408  EXPECT_EQ(fl_value_get_int(details), 42);
409 }
G_BEGIN_DECLS FlValue * args
static FlTestMethodCodec * fl_test_method_codec_new()
G_MODULE_EXPORT FlMethodSuccessResponse * fl_method_success_response_new(FlValue *result)
GBytes * fl_method_codec_encode_method_call(FlMethodCodec *self, const gchar *name, FlValue *args, GError **error)
G_MODULE_EXPORT FlValueType fl_value_get_type(FlValue *self)
Definition: fl_value.cc:395
G_DECLARE_FINAL_TYPE(FlTestMethodCodec, fl_test_method_codec, FL, TEST_METHOD_CODEC, FlMethodCodec) struct _FlTestMethodCodec
typedefG_BEGIN_DECLS struct _FlValue FlValue
Definition: fl_value.h:39
FlMethodResponse GError ** error
static gboolean fl_test_codec_decode_method_call(FlMethodCodec *codec, GBytes *message, gchar **name, FlValue **args, GError **error)
G_MODULE_EXPORT int64_t fl_value_get_int(FlValue *self)
Definition: fl_value.cc:582
G_MODULE_EXPORT FlValue * fl_method_success_response_get_result(FlMethodSuccessResponse *self)
#define FL_MESSAGE_CODEC_ERROR
G_MODULE_EXPORT const gchar * fl_method_error_response_get_message(FlMethodErrorResponse *self)
G_MODULE_EXPORT FlValue * fl_value_new_bool(bool value)
Definition: fl_value.cc:226
static GBytes * fl_test_codec_encode_success_envelope(FlMethodCodec *codec, FlValue *result, GError **error)
G_DEFINE_TYPE(FlTestMethodCodec, fl_test_method_codec, fl_method_codec_get_type()) static gchar *message_to_text(GBytes *message)
static void fl_test_method_codec_init(FlTestMethodCodec *self)
static FlMethodResponse * fl_test_codec_decode_response(FlMethodCodec *codec, GBytes *message, GError **error)
static gchar * message_to_text(GBytes *message)
FlMethodResponse * fl_method_codec_decode_response(FlMethodCodec *self, GBytes *message, GError **error)
G_MODULE_EXPORT FlValue * fl_value_new_int(int64_t value)
Definition: fl_value.cc:233
G_MODULE_EXPORT FlValue * fl_value_new_string(const gchar *value)
Definition: fl_value.cc:247
const char * name
Definition: fuchsia.cc:50
static GBytes * text_to_message(const gchar *text)
return TRUE
Definition: fl_view.cc:107
G_MODULE_EXPORT const gchar * fl_value_get_string(FlValue *self)
Definition: fl_value.cc:596
G_MODULE_EXPORT const gchar * fl_method_error_response_get_code(FlMethodErrorResponse *self)
GBytes * fl_method_codec_encode_error_envelope(FlMethodCodec *self, const gchar *code, const gchar *message, FlValue *details, GError **error)
G_MODULE_EXPORT GType fl_method_codec_get_type()
TEST(FlMethodCodecTest, EncodeMethodCall)
static GBytes * fl_test_codec_encode_error_envelope(FlMethodCodec *codec, const gchar *code, const gchar *message, FlValue *details, GError **error)
static void fl_test_method_codec_class_init(FlTestMethodCodecClass *klass)
G_BEGIN_DECLS FL
GBytes * fl_method_codec_encode_success_envelope(FlMethodCodec *self, FlValue *result, GError **error)
gboolean fl_method_codec_decode_method_call(FlMethodCodec *self, GBytes *message, gchar **name, FlValue **args, GError **error)
G_MODULE_EXPORT FlValue * fl_method_error_response_get_details(FlMethodErrorResponse *self)
G_MODULE_EXPORT FlMethodErrorResponse * fl_method_error_response_new(const gchar *code, const gchar *message, FlValue *details)
G_MODULE_EXPORT FlValue * fl_value_new_null()
Definition: fl_value.cc:222
static GBytes * fl_test_codec_encode_method_call(FlMethodCodec *codec, const gchar *name, FlValue *args, GError **error)