Flutter Engine
The 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.
15static 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.
23static 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.
28static 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;
32 FL_METHOD_CODEC(codec), name, args, &error);
33 EXPECT_NE(message, nullptr);
34 EXPECT_EQ(error, nullptr);
35
37}
38
39// Encodes a success envelope response using JsonMethodCodec to a UTF-8 string.
41 g_autoptr(FlJsonMethodCodec) codec = fl_json_method_codec_new();
42 g_autoptr(GError) error = nullptr;
44 FL_METHOD_CODEC(codec), result, &error);
45 EXPECT_NE(message, nullptr);
46 EXPECT_EQ(error, nullptr);
47
49}
50
51// Encodes a error envelope response using JsonMethodCodec to a UTF8 string.
52static 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;
58 FL_METHOD_CODEC(codec), error_code, error_message, details, &error);
59 EXPECT_NE(message, nullptr);
60 EXPECT_EQ(error, nullptr);
61
63}
64
65// Decodes a method call using JsonMethodCodec with a UTF8 string.
66static 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;
71 FL_METHOD_CODEC(codec), data, name, args, &error);
73 EXPECT_EQ(error, nullptr);
74}
75
76// Decodes a method call using JsonMethodCodec. Expect the given error.
77static 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;
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.
94static 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.
110static 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.
146static 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
156TEST(FlJsonMethodCodecTest, EncodeMethodCallNullptrArgs) {
157 g_autofree gchar* text = encode_method_call("hello", nullptr);
158 EXPECT_STREQ(text, "{\"method\":\"hello\",\"args\":null}");
159}
160
161TEST(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
167TEST(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
173TEST(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
181TEST(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
189TEST(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");
195}
196
197TEST(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");
203 EXPECT_STREQ(fl_value_get_string(args), "world");
204}
205
206TEST(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");
213 EXPECT_EQ(fl_value_get_length(args), static_cast<size_t>(2));
214
216 ASSERT_EQ(fl_value_get_type(arg0), FL_VALUE_TYPE_STRING);
217 EXPECT_STREQ(fl_value_get_string(arg0), "count");
218
220 ASSERT_EQ(fl_value_get_type(arg1), FL_VALUE_TYPE_INT);
221 EXPECT_EQ(fl_value_get_int(arg1), 42);
222}
223
224TEST(FlJsonMethodCodecTest, DecodeMethodCallNoData) {
227}
228
229TEST(FlJsonMethodCodecTest, DecodeMethodCallNoMethodOrArgs) {
232}
233
234TEST(FlJsonMethodCodecTest, DecodeMethodCallInvalidJson) {
237}
238
239TEST(FlJsonMethodCodecTest, DecodeMethodCallWrongType) {
242}
243
244TEST(FlJsonMethodCodecTest, DecodeMethodCallNoMethod) {
245 decode_error_method_call("{\"args\":\"world\"}", FL_MESSAGE_CODEC_ERROR,
247}
248
249TEST(FlJsonMethodCodecTest, DecodeMethodCallNoTerminator) {
250 decode_error_method_call("{\"method\":\"hello\",\"args\":\"world\"",
253}
254
255TEST(FlJsonMethodCodecTest, DecodeMethodCallExtraData) {
256 decode_error_method_call("{\"method\":\"hello\"}XXX",
259}
260
261TEST(FlJsonMethodCodecTest, EncodeSuccessEnvelopeNullptr) {
262 g_autofree gchar* text = encode_success_envelope(nullptr);
263 EXPECT_STREQ(text, "[null]");
264}
265
266TEST(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
272TEST(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
278TEST(FlJsonMethodCodecTest, EncodeSuccessEnvelopeList) {
279 g_autoptr(FlValue) result = fl_value_new_list();
282 g_autofree gchar* text = encode_success_envelope(result);
283 EXPECT_STREQ(text, "[[\"count\",42]]");
284}
285
286TEST(FlJsonMethodCodecTest, EncodeErrorEnvelopeEmptyCode) {
287 g_autofree gchar* text = encode_error_envelope("", nullptr, nullptr);
288 EXPECT_STREQ(text, "[\"\",null,null]");
289}
290
291TEST(FlJsonMethodCodecTest, EncodeErrorEnvelopeNonMessageOrDetails) {
292 g_autofree gchar* text = encode_error_envelope("error", nullptr, nullptr);
293 EXPECT_STREQ(text, "[\"error\",null,null]");
294}
295
296TEST(FlJsonMethodCodecTest, EncodeErrorEnvelopeMessage) {
297 g_autofree gchar* text = encode_error_envelope("error", "message", nullptr);
298 EXPECT_STREQ(text, "[\"error\",\"message\",null]");
299}
300
301TEST(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
309TEST(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
317TEST(FlJsonMethodCodecTest, DecodeResponseSuccessNull) {
318 g_autoptr(FlValue) result = fl_value_new_null();
320}
321
322TEST(FlJsonMethodCodecTest, DecodeResponseSuccessString) {
323 g_autoptr(FlValue) result = fl_value_new_string("hello");
324 decode_response_with_success("[\"hello\"]", result);
325}
326
327TEST(FlJsonMethodCodecTest, DecodeResponseSuccessList) {
328 g_autoptr(FlValue) result = fl_value_new_list();
331 decode_response_with_success("[[\"count\",42]]", result);
332}
333
334TEST(FlJsonMethodCodecTest, DecodeResponseErrorEmptyCode) {
335 decode_response_with_error("[\"\",null,null]", "", nullptr, nullptr);
336}
337
338TEST(FlJsonMethodCodecTest, DecodeResponseErrorNoMessageOrDetails) {
339 decode_response_with_error("[\"error\",null,null]", "error", nullptr,
340 nullptr);
341}
342
343TEST(FlJsonMethodCodecTest, DecodeResponseErrorMessage) {
344 decode_response_with_error("[\"error\",\"message\",null]", "error", "message",
345 nullptr);
346}
347
348TEST(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
356TEST(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
364TEST(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
375TEST(FlJsonMethodCodecTest, DecodeResponseNoTerminator) {
378}
379
380TEST(FlJsonMethodCodecTest, DecodeResponseInvalidJson) {
383}
384
385TEST(FlJsonMethodCodecTest, DecodeResponseMissingDetails) {
386 decode_error_response("[\"error\",\"message\"]", FL_MESSAGE_CODEC_ERROR,
388}
389
390TEST(FlJsonMethodCodecTest, DecodeResponseExtraDetails) {
391 decode_error_response("[\"error\",\"message\",true,42]",
393}
394
395TEST(FlJsonMethodCodecTest, DecodeResponseSuccessExtraData) {
398}
399
400TEST(FlJsonMethodCodecTest, DecodeResponseErrorExtraData) {
401 decode_error_response("[\"error\",null,null]X", FL_JSON_MESSAGE_CODEC_ERROR,
403}
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
@ FL_JSON_MESSAGE_CODEC_ERROR_INVALID_JSON
#define FL_JSON_MESSAGE_CODEC_ERROR
G_MODULE_EXPORT FlJsonMethodCodec * fl_json_method_codec_new()
static void decode_error_method_call(const char *text, GQuark domain, gint code)
static void decode_error_response(const char *text, GQuark domain, gint code)
TEST(FlJsonMethodCodecTest, EncodeMethodCallNullptrArgs)
static void decode_response_with_success(const char *text, FlValue *result)
static void decode_response_with_error(const char *text, const gchar *code, const gchar *error_message, FlValue *details)
static gchar * encode_method_call(const gchar *name, FlValue *args)
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_method_call(const char *text, gchar **name, FlValue **args)
static gchar * encode_success_envelope(FlValue *result)
static GBytes * text_to_message(const gchar *text)
@ FL_MESSAGE_CODEC_ERROR_FAILED
#define FL_MESSAGE_CODEC_ERROR
FlMethodResponse * fl_method_codec_decode_response(FlMethodCodec *self, GBytes *message, GError **error)
gboolean fl_method_codec_decode_method_call(FlMethodCodec *self, GBytes *message, gchar **name, FlValue **args, GError **error)
GBytes * fl_method_codec_encode_success_envelope(FlMethodCodec *self, FlValue *result, GError **error)
GBytes * fl_method_codec_encode_method_call(FlMethodCodec *self, const gchar *name, FlValue *args, GError **error)
GBytes * fl_method_codec_encode_error_envelope(FlMethodCodec *self, const gchar *code, const gchar *message, FlValue *details, GError **error)
G_MODULE_EXPORT FlValue * fl_method_success_response_get_result(FlMethodSuccessResponse *self)
G_MODULE_EXPORT const gchar * fl_method_error_response_get_message(FlMethodErrorResponse *self)
G_MODULE_EXPORT FlValue * fl_method_error_response_get_details(FlMethodErrorResponse *self)
G_MODULE_EXPORT const gchar * fl_method_error_response_get_code(FlMethodErrorResponse *self)
const uint8_t uint32_t uint32_t GError ** error
uint8_t value
GAsyncResult * result
G_MODULE_EXPORT int64_t fl_value_get_int(FlValue *self)
Definition: fl_value.cc:668
G_MODULE_EXPORT FlValueType fl_value_get_type(FlValue *self)
Definition: fl_value.cc:466
G_MODULE_EXPORT FlValue * fl_value_new_null()
Definition: fl_value.cc:251
G_MODULE_EXPORT FlValue * fl_value_new_string(const gchar *value)
Definition: fl_value.cc:276
G_MODULE_EXPORT const gchar * fl_value_get_string(FlValue *self)
Definition: fl_value.cc:682
G_MODULE_EXPORT FlValue * fl_value_new_int(int64_t value)
Definition: fl_value.cc:262
G_MODULE_EXPORT void fl_value_append_take(FlValue *self, FlValue *value)
Definition: fl_value.cc:600
G_MODULE_EXPORT FlValue * fl_value_get_list_value(FlValue *self, size_t index)
Definition: fl_value.cc:776
G_MODULE_EXPORT FlValue * fl_value_new_list()
Definition: fl_value.cc:349
G_MODULE_EXPORT bool fl_value_equal(FlValue *a, FlValue *b)
Definition: fl_value.cc:471
G_MODULE_EXPORT size_t fl_value_get_length(FlValue *self)
Definition: fl_value.cc:724
typedefG_BEGIN_DECLS struct _FlValue FlValue
Definition: fl_value.h:42
@ FL_VALUE_TYPE_STRING
Definition: fl_value.h:69
@ FL_VALUE_TYPE_NULL
Definition: fl_value.h:65
@ FL_VALUE_TYPE_INT
Definition: fl_value.h:67
@ FL_VALUE_TYPE_LIST
Definition: fl_value.h:74
std::u16string text
Win32Message message
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63
#define EXPECT_TRUE(handle)
Definition: unit_test.h:678