Flutter Engine
fl_json_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_json_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_json_message_codec.h"
11 #include "flutter/shell/platform/linux/public/flutter_linux/fl_message_codec.h"
12 #include "gtest/gtest.h"
13 
14 // Converts a binary blob to a string.
15 static gchar* message_to_text(GBytes* message) {
16  size_t data_length;
17  const gchar* data =
18  static_cast<const gchar*>(g_bytes_get_data(message, &data_length));
19  return g_strndup(data, data_length);
20 }
21 
22 // Converts a string to a binary blob.
23 static GBytes* text_to_message(const gchar* text) {
24  return g_bytes_new(text, strlen(text));
25 }
26 
27 // Encodes a method call using JsonMethodCodec to a UTF-8 string.
28 static gchar* encode_method_call(const gchar* name, FlValue* args) {
29  g_autoptr(FlJsonMethodCodec) codec = fl_json_method_codec_new();
30  g_autoptr(GError) error = nullptr;
31  g_autoptr(GBytes) message = fl_method_codec_encode_method_call(
32  FL_METHOD_CODEC(codec), name, args, &error);
33  EXPECT_NE(message, nullptr);
34  EXPECT_EQ(error, nullptr);
35 
36  return message_to_text(message);
37 }
38 
39 // Encodes a success envelope response using JsonMethodCodec to a UTF-8 string.
40 static gchar* encode_success_envelope(FlValue* result) {
41  g_autoptr(FlJsonMethodCodec) codec = fl_json_method_codec_new();
42  g_autoptr(GError) error = nullptr;
43  g_autoptr(GBytes) message = fl_method_codec_encode_success_envelope(
44  FL_METHOD_CODEC(codec), result, &error);
45  EXPECT_NE(message, nullptr);
46  EXPECT_EQ(error, nullptr);
47 
48  return message_to_text(message);
49 }
50 
51 // Encodes a error envelope response using JsonMethodCodec to a UTF8 string.
52 static gchar* encode_error_envelope(const gchar* error_code,
53  const gchar* error_message,
54  FlValue* details) {
55  g_autoptr(FlJsonMethodCodec) codec = fl_json_method_codec_new();
56  g_autoptr(GError) error = nullptr;
57  g_autoptr(GBytes) message = fl_method_codec_encode_error_envelope(
58  FL_METHOD_CODEC(codec), error_code, error_message, details, &error);
59  EXPECT_NE(message, nullptr);
60  EXPECT_EQ(error, nullptr);
61 
62  return message_to_text(message);
63 }
64 
65 // Decodes a method call using JsonMethodCodec with a UTF8 string.
66 static void decode_method_call(const char* text, gchar** name, FlValue** args) {
67  g_autoptr(FlJsonMethodCodec) codec = fl_json_method_codec_new();
68  g_autoptr(GBytes) data = text_to_message(text);
69  g_autoptr(GError) error = nullptr;
70  gboolean result = fl_method_codec_decode_method_call(
71  FL_METHOD_CODEC(codec), data, name, args, &error);
72  EXPECT_TRUE(result);
73  EXPECT_EQ(error, nullptr);
74 }
75 
76 // Decodes a method call using JsonMethodCodec. Expect the given error.
77 static void decode_error_method_call(const char* text,
78  GQuark domain,
79  gint code) {
80  g_autoptr(FlJsonMethodCodec) codec = fl_json_method_codec_new();
81  g_autoptr(GBytes) data = text_to_message(text);
82  g_autoptr(GError) error = nullptr;
83  g_autofree gchar* name = nullptr;
84  g_autoptr(FlValue) args = nullptr;
85  gboolean result = fl_method_codec_decode_method_call(
86  FL_METHOD_CODEC(codec), data, &name, &args, &error);
87  EXPECT_FALSE(result);
88  EXPECT_EQ(name, nullptr);
89  EXPECT_EQ(args, nullptr);
90  EXPECT_TRUE(g_error_matches(error, domain, code));
91 }
92 
93 // Decodes a response using JsonMethodCodec. Expect the response is a result.
94 static void decode_response_with_success(const char* text, FlValue* result) {
95  g_autoptr(FlJsonMethodCodec) codec = fl_json_method_codec_new();
96  g_autoptr(GBytes) message = text_to_message(text);
97  g_autoptr(GError) error = nullptr;
98  g_autoptr(FlMethodResponse) response =
99  fl_method_codec_decode_response(FL_METHOD_CODEC(codec), message, &error);
100  ASSERT_NE(response, nullptr);
101  EXPECT_EQ(error, nullptr);
102  ASSERT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response));
104  FL_METHOD_SUCCESS_RESPONSE(response)),
105  result));
106 }
107 
108 // Decodes a response using JsonMethodCodec. Expect the response contains the
109 // given error.
110 static void decode_response_with_error(const char* text,
111  const gchar* code,
112  const gchar* error_message,
113  FlValue* details) {
114  g_autoptr(FlJsonMethodCodec) codec = fl_json_method_codec_new();
115  g_autoptr(GBytes) message = text_to_message(text);
116  g_autoptr(GError) error = nullptr;
117  g_autoptr(FlMethodResponse) response =
118  fl_method_codec_decode_response(FL_METHOD_CODEC(codec), message, &error);
119  ASSERT_NE(response, nullptr);
120  EXPECT_EQ(error, nullptr);
121  ASSERT_TRUE(FL_IS_METHOD_ERROR_RESPONSE(response));
122  EXPECT_STREQ(
123  fl_method_error_response_get_code(FL_METHOD_ERROR_RESPONSE(response)),
124  code);
125  if (error_message == nullptr) {
127  FL_METHOD_ERROR_RESPONSE(response)),
128  nullptr);
129  } else {
131  FL_METHOD_ERROR_RESPONSE(response)),
132  error_message);
133  }
134  if (details == nullptr) {
136  FL_METHOD_ERROR_RESPONSE(response)),
137  nullptr);
138  } else {
140  FL_METHOD_ERROR_RESPONSE(response)),
141  details));
142  }
143 }
144 
145 // Decode a response using JsonMethodCodec. Expect the given error.
146 static void decode_error_response(const char* text, GQuark domain, gint code) {
147  g_autoptr(FlJsonMethodCodec) codec = fl_json_method_codec_new();
148  g_autoptr(GBytes) message = text_to_message(text);
149  g_autoptr(GError) error = nullptr;
150  g_autoptr(FlMethodResponse) response =
151  fl_method_codec_decode_response(FL_METHOD_CODEC(codec), message, &error);
152  EXPECT_EQ(response, nullptr);
153  EXPECT_TRUE(g_error_matches(error, domain, code));
154 }
155 
156 TEST(FlJsonMethodCodecTest, EncodeMethodCallNullptrArgs) {
157  g_autofree gchar* text = encode_method_call("hello", nullptr);
158  EXPECT_STREQ(text, "{\"method\":\"hello\",\"args\":null}");
159 }
160 
161 TEST(FlJsonMethodCodecTest, EncodeMethodCallNullArgs) {
162  g_autoptr(FlValue) value = fl_value_new_null();
163  g_autofree gchar* text = encode_method_call("hello", value);
164  EXPECT_STREQ(text, "{\"method\":\"hello\",\"args\":null}");
165 }
166 
167 TEST(FlJsonMethodCodecTest, EncodeMethodCallStringArgs) {
168  g_autoptr(FlValue) args = fl_value_new_string("world");
169  g_autofree gchar* text = encode_method_call("hello", args);
170  EXPECT_STREQ(text, "{\"method\":\"hello\",\"args\":\"world\"}");
171 }
172 
173 TEST(FlJsonMethodCodecTest, EncodeMethodCallListArgs) {
174  g_autoptr(FlValue) args = fl_value_new_list();
177  g_autofree gchar* text = encode_method_call("hello", args);
178  EXPECT_STREQ(text, "{\"method\":\"hello\",\"args\":[\"count\",42]}");
179 }
180 
181 TEST(FlJsonMethodCodecTest, DecodeMethodCallNoArgs) {
182  g_autofree gchar* name = nullptr;
183  g_autoptr(FlValue) args = nullptr;
184  decode_method_call("{\"method\":\"hello\"}", &name, &args);
185  EXPECT_STREQ(name, "hello");
186  ASSERT_EQ(args, nullptr);
187 }
188 
189 TEST(FlJsonMethodCodecTest, DecodeMethodCallNullArgs) {
190  g_autofree gchar* name = nullptr;
191  g_autoptr(FlValue) args = nullptr;
192  decode_method_call("{\"method\":\"hello\",\"args\":null}", &name, &args);
193  EXPECT_STREQ(name, "hello");
194  ASSERT_EQ(fl_value_get_type(args), FL_VALUE_TYPE_NULL);
195 }
196 
197 TEST(FlJsonMethodCodecTest, DecodeMethodCallStringArgs) {
198  g_autofree gchar* name = nullptr;
199  g_autoptr(FlValue) args = nullptr;
200  decode_method_call("{\"method\":\"hello\",\"args\":\"world\"}", &name, &args);
201  EXPECT_STREQ(name, "hello");
202  ASSERT_EQ(fl_value_get_type(args), FL_VALUE_TYPE_STRING);
203  EXPECT_STREQ(fl_value_get_string(args), "world");
204 }
205 
206 TEST(FlJsonMethodCodecTest, DecodeMethodCallListArgs) {
207  g_autofree gchar* name = nullptr;
208  g_autoptr(FlValue) args = nullptr;
209  decode_method_call("{\"method\":\"hello\",\"args\":[\"count\",42]}", &name,
210  &args);
211  EXPECT_STREQ(name, "hello");
212  ASSERT_EQ(fl_value_get_type(args), FL_VALUE_TYPE_LIST);
213  EXPECT_EQ(fl_value_get_length(args), static_cast<size_t>(2));
214 
215  FlValue* arg0 = fl_value_get_list_value(args, 0);
216  ASSERT_EQ(fl_value_get_type(arg0), FL_VALUE_TYPE_STRING);
217  EXPECT_STREQ(fl_value_get_string(arg0), "count");
218 
219  FlValue* arg1 = fl_value_get_list_value(args, 1);
220  ASSERT_EQ(fl_value_get_type(arg1), FL_VALUE_TYPE_INT);
221  EXPECT_EQ(fl_value_get_int(arg1), 42);
222 }
223 
224 TEST(FlJsonMethodCodecTest, DecodeMethodCallNoData) {
227 }
228 
229 TEST(FlJsonMethodCodecTest, DecodeMethodCallNoMethodOrArgs) {
232 }
233 
234 TEST(FlJsonMethodCodecTest, DecodeMethodCallInvalidJson) {
237 }
238 
239 TEST(FlJsonMethodCodecTest, DecodeMethodCallWrongType) {
242 }
243 
244 TEST(FlJsonMethodCodecTest, DecodeMethodCallNoMethod) {
245  decode_error_method_call("{\"args\":\"world\"}", FL_MESSAGE_CODEC_ERROR,
247 }
248 
249 TEST(FlJsonMethodCodecTest, DecodeMethodCallNoTerminator) {
250  decode_error_method_call("{\"method\":\"hello\",\"args\":\"world\"",
253 }
254 
255 TEST(FlJsonMethodCodecTest, DecodeMethodCallExtraData) {
256  decode_error_method_call("{\"method\":\"hello\"}XXX",
259 }
260 
261 TEST(FlJsonMethodCodecTest, EncodeSuccessEnvelopeNullptr) {
262  g_autofree gchar* text = encode_success_envelope(nullptr);
263  EXPECT_STREQ(text, "[null]");
264 }
265 
266 TEST(FlJsonMethodCodecTest, EncodeSuccessEnvelopeNull) {
267  g_autoptr(FlValue) result = fl_value_new_null();
268  g_autofree gchar* text = encode_success_envelope(result);
269  EXPECT_STREQ(text, "[null]");
270 }
271 
272 TEST(FlJsonMethodCodecTest, EncodeSuccessEnvelopeString) {
273  g_autoptr(FlValue) result = fl_value_new_string("hello");
274  g_autofree gchar* text = encode_success_envelope(result);
275  EXPECT_STREQ(text, "[\"hello\"]");
276 }
277 
278 TEST(FlJsonMethodCodecTest, EncodeSuccessEnvelopeList) {
279  g_autoptr(FlValue) result = fl_value_new_list();
280  fl_value_append_take(result, fl_value_new_string("count"));
282  g_autofree gchar* text = encode_success_envelope(result);
283  EXPECT_STREQ(text, "[[\"count\",42]]");
284 }
285 
286 TEST(FlJsonMethodCodecTest, EncodeErrorEnvelopeEmptyCode) {
287  g_autofree gchar* text = encode_error_envelope("", nullptr, nullptr);
288  EXPECT_STREQ(text, "[\"\",null,null]");
289 }
290 
291 TEST(FlJsonMethodCodecTest, EncodeErrorEnvelopeNonMessageOrDetails) {
292  g_autofree gchar* text = encode_error_envelope("error", nullptr, nullptr);
293  EXPECT_STREQ(text, "[\"error\",null,null]");
294 }
295 
296 TEST(FlJsonMethodCodecTest, EncodeErrorEnvelopeMessage) {
297  g_autofree gchar* text = encode_error_envelope("error", "message", nullptr);
298  EXPECT_STREQ(text, "[\"error\",\"message\",null]");
299 }
300 
301 TEST(FlJsonMethodCodecTest, EncodeErrorEnvelopeDetails) {
302  g_autoptr(FlValue) details = fl_value_new_list();
303  fl_value_append_take(details, fl_value_new_string("count"));
305  g_autofree gchar* text = encode_error_envelope("error", nullptr, details);
306  EXPECT_STREQ(text, "[\"error\",null,[\"count\",42]]");
307 }
308 
309 TEST(FlJsonMethodCodecTest, EncodeErrorEnvelopeMessageAndDetails) {
310  g_autoptr(FlValue) details = fl_value_new_list();
311  fl_value_append_take(details, fl_value_new_string("count"));
313  g_autofree gchar* text = encode_error_envelope("error", "message", details);
314  EXPECT_STREQ(text, "[\"error\",\"message\",[\"count\",42]]");
315 }
316 
317 TEST(FlJsonMethodCodecTest, DecodeResponseSuccessNull) {
318  g_autoptr(FlValue) result = fl_value_new_null();
319  decode_response_with_success("[null]", result);
320 }
321 
322 TEST(FlJsonMethodCodecTest, DecodeResponseSuccessString) {
323  g_autoptr(FlValue) result = fl_value_new_string("hello");
324  decode_response_with_success("[\"hello\"]", result);
325 }
326 
327 TEST(FlJsonMethodCodecTest, DecodeResponseSuccessList) {
328  g_autoptr(FlValue) result = fl_value_new_list();
329  fl_value_append_take(result, fl_value_new_string("count"));
331  decode_response_with_success("[[\"count\",42]]", result);
332 }
333 
334 TEST(FlJsonMethodCodecTest, DecodeResponseErrorEmptyCode) {
335  decode_response_with_error("[\"\",null,null]", "", nullptr, nullptr);
336 }
337 
338 TEST(FlJsonMethodCodecTest, DecodeResponseErrorNoMessageOrDetails) {
339  decode_response_with_error("[\"error\",null,null]", "error", nullptr,
340  nullptr);
341 }
342 
343 TEST(FlJsonMethodCodecTest, DecodeResponseErrorMessage) {
344  decode_response_with_error("[\"error\",\"message\",null]", "error", "message",
345  nullptr);
346 }
347 
348 TEST(FlJsonMethodCodecTest, DecodeResponseErrorDetails) {
349  g_autoptr(FlValue) details = fl_value_new_list();
350  fl_value_append_take(details, fl_value_new_string("count"));
352  decode_response_with_error("[\"error\",null,[\"count\",42]]", "error",
353  nullptr, details);
354 }
355 
356 TEST(FlJsonMethodCodecTest, DecodeResponseErrorMessageAndDetails) {
357  g_autoptr(FlValue) details = fl_value_new_list();
358  fl_value_append_take(details, fl_value_new_string("count"));
360  decode_response_with_error("[\"error\",\"message\",[\"count\",42]]", "error",
361  "message", details);
362 }
363 
364 TEST(FlJsonMethodCodecTest, DecodeResponseNotImplemented) {
365  g_autoptr(FlJsonMethodCodec) codec = fl_json_method_codec_new();
366  g_autoptr(GBytes) message = g_bytes_new(nullptr, 0);
367  g_autoptr(GError) error = nullptr;
368  g_autoptr(FlMethodResponse) response =
369  fl_method_codec_decode_response(FL_METHOD_CODEC(codec), message, &error);
370  ASSERT_NE(response, nullptr);
371  EXPECT_EQ(error, nullptr);
372  EXPECT_TRUE(FL_IS_METHOD_NOT_IMPLEMENTED_RESPONSE(response));
373 }
374 
375 TEST(FlJsonMethodCodecTest, DecodeResponseNoTerminator) {
378 }
379 
380 TEST(FlJsonMethodCodecTest, DecodeResponseInvalidJson) {
383 }
384 
385 TEST(FlJsonMethodCodecTest, DecodeResponseMissingDetails) {
386  decode_error_response("[\"error\",\"message\"]", FL_MESSAGE_CODEC_ERROR,
388 }
389 
390 TEST(FlJsonMethodCodecTest, DecodeResponseExtraDetails) {
391  decode_error_response("[\"error\",\"message\",true,42]",
393 }
394 
395 TEST(FlJsonMethodCodecTest, DecodeResponseSuccessExtraData) {
398 }
399 
400 TEST(FlJsonMethodCodecTest, DecodeResponseErrorExtraData) {
401  decode_error_response("[\"error\",null,null]X", FL_JSON_MESSAGE_CODEC_ERROR,
403 }
G_MODULE_EXPORT FlValue * fl_value_new_list()
Definition: fl_value.cc:310
GBytes * fl_method_codec_encode_method_call(FlMethodCodec *self, const gchar *name, FlValue *args, GError **error)
static void decode_response_with_error(const char *text, const gchar *code, const gchar *error_message, FlValue *details)
G_MODULE_EXPORT FlValueType fl_value_get_type(FlValue *self)
Definition: fl_value.cc:395
typedefG_BEGIN_DECLS struct _FlValue FlValue
Definition: fl_value.h:39
G_MODULE_EXPORT FlJsonMethodCodec * fl_json_method_codec_new()
FlMethodResponse GError ** error
#define FL_JSON_MESSAGE_CODEC_ERROR
G_MODULE_EXPORT int64_t fl_value_get_int(FlValue *self)
Definition: fl_value.cc:582
static void decode_method_call(const char *text, gchar **name, FlValue **args)
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)
static void decode_error_method_call(const char *text, GQuark domain, gint code)
G_MODULE_EXPORT bool fl_value_equal(FlValue *a, FlValue *b)
Definition: fl_value.cc:400
static gchar * encode_success_envelope(FlValue *result)
static GBytes * text_to_message(const gchar *text)
G_MODULE_EXPORT void fl_value_append_take(FlValue *self, FlValue *value)
Definition: fl_value.cc:514
uint8_t value
static gchar * encode_error_envelope(const gchar *error_code, const gchar *error_message, FlValue *details)
static gchar * message_to_text(GBytes *message)
static void decode_response_with_success(const char *text, FlValue *result)
G_MODULE_EXPORT FlValue * fl_value_get_list_value(FlValue *self, size_t index)
Definition: fl_value.cc:677
static gchar * encode_method_call(const gchar *name, FlValue *args)
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
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)
TEST(FlJsonMethodCodecTest, EncodeMethodCallNullptrArgs)
GBytes * fl_method_codec_encode_success_envelope(FlMethodCodec *self, FlValue *result, GError **error)
G_MODULE_EXPORT size_t fl_value_get_length(FlValue *self)
Definition: fl_value.cc:631
static void decode_error_response(const char *text, GQuark domain, gint code)
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 FlValue * fl_value_new_null()
Definition: fl_value.cc:222