| // Copyright 2013 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "flutter/shell/platform/linux/public/flutter_linux/fl_standard_method_codec.h" |
| #include "flutter/shell/platform/linux/fl_method_codec_private.h" |
| #include "flutter/shell/platform/linux/public/flutter_linux/fl_message_codec.h" |
| #include "flutter/shell/platform/linux/testing/fl_test.h" |
| #include "gtest/gtest.h" |
| |
| // NOTE(robert-ancell) These test cases assumes a little-endian architecture. |
| // These tests will need to be updated if tested on a big endian architecture. |
| |
| // Encodes a method call using StandardMethodCodec to a hex string. |
| static gchar* encode_method_call(const gchar* name, FlValue* args) { |
| g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new(); |
| g_autoptr(GError) error = nullptr; |
| g_autoptr(GBytes) message = fl_method_codec_encode_method_call( |
| FL_METHOD_CODEC(codec), name, args, &error); |
| EXPECT_NE(message, nullptr); |
| EXPECT_EQ(error, nullptr); |
| |
| return bytes_to_hex_string(message); |
| } |
| |
| // Encodes a success envelope response using StandardMethodCodec to a hex |
| // string. |
| static gchar* encode_success_envelope(FlValue* result) { |
| g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new(); |
| g_autoptr(GError) error = nullptr; |
| g_autoptr(GBytes) message = fl_method_codec_encode_success_envelope( |
| FL_METHOD_CODEC(codec), result, &error); |
| EXPECT_NE(message, nullptr); |
| EXPECT_EQ(error, nullptr); |
| |
| return bytes_to_hex_string(message); |
| } |
| |
| // Encodes a error envelope response using StandardMethodCodec to a hex string. |
| static gchar* encode_error_envelope(const gchar* error_code, |
| const gchar* error_message, |
| FlValue* details) { |
| g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new(); |
| g_autoptr(GError) error = nullptr; |
| g_autoptr(GBytes) message = fl_method_codec_encode_error_envelope( |
| FL_METHOD_CODEC(codec), error_code, error_message, details, &error); |
| EXPECT_NE(message, nullptr); |
| EXPECT_EQ(error, nullptr); |
| |
| return bytes_to_hex_string(message); |
| } |
| |
| // Decodes a method call using StandardMethodCodec with a hex string. |
| static void decode_method_call(const char* hex_string, |
| gchar** name, |
| FlValue** args) { |
| g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new(); |
| g_autoptr(GBytes) message = hex_string_to_bytes(hex_string); |
| g_autoptr(GError) error = nullptr; |
| gboolean result = fl_method_codec_decode_method_call( |
| FL_METHOD_CODEC(codec), message, name, args, &error); |
| EXPECT_TRUE(result); |
| EXPECT_EQ(error, nullptr); |
| } |
| |
| // Decodes a method call using StandardMethodCodec. Expect the given error. |
| static void decode_error_method_call(const char* hex_string, |
| GQuark domain, |
| gint code) { |
| g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new(); |
| g_autoptr(GBytes) message = hex_string_to_bytes(hex_string); |
| g_autoptr(GError) error = nullptr; |
| g_autofree gchar* name = nullptr; |
| g_autoptr(FlValue) args = nullptr; |
| gboolean result = fl_method_codec_decode_method_call( |
| FL_METHOD_CODEC(codec), message, &name, &args, &error); |
| EXPECT_FALSE(result); |
| EXPECT_EQ(name, nullptr); |
| EXPECT_EQ(args, nullptr); |
| EXPECT_TRUE(g_error_matches(error, domain, code)); |
| } |
| |
| // Decodes a response using StandardMethodCodec. Expect the response is a |
| // result. |
| static void decode_response_with_success(const char* hex_string, |
| FlValue* result) { |
| g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new(); |
| g_autoptr(GBytes) message = hex_string_to_bytes(hex_string); |
| g_autoptr(GError) error = nullptr; |
| g_autoptr(FlMethodResponse) response = |
| fl_method_codec_decode_response(FL_METHOD_CODEC(codec), message, &error); |
| ASSERT_NE(response, nullptr); |
| EXPECT_EQ(error, nullptr); |
| EXPECT_TRUE(FL_IS_METHOD_SUCCESS_RESPONSE(response)); |
| EXPECT_TRUE(fl_value_equal(fl_method_success_response_get_result( |
| FL_METHOD_SUCCESS_RESPONSE(response)), |
| result)); |
| } |
| |
| // Decodes a response using StandardMethodCodec. Expect the response contains |
| // the given error. |
| static void decode_response_with_error(const char* hex_string, |
| const gchar* code, |
| const gchar* error_message, |
| FlValue* details) { |
| g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new(); |
| g_autoptr(GBytes) message = hex_string_to_bytes(hex_string); |
| g_autoptr(GError) error = nullptr; |
| g_autoptr(FlMethodResponse) response = |
| fl_method_codec_decode_response(FL_METHOD_CODEC(codec), message, &error); |
| ASSERT_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); |
| if (error_message == nullptr) { |
| EXPECT_EQ(fl_method_error_response_get_message( |
| FL_METHOD_ERROR_RESPONSE(response)), |
| nullptr); |
| } else { |
| EXPECT_STREQ(fl_method_error_response_get_message( |
| FL_METHOD_ERROR_RESPONSE(response)), |
| error_message); |
| } |
| if (details == nullptr) { |
| EXPECT_EQ(fl_method_error_response_get_details( |
| FL_METHOD_ERROR_RESPONSE(response)), |
| nullptr); |
| } else { |
| EXPECT_TRUE(fl_value_equal(fl_method_error_response_get_details( |
| FL_METHOD_ERROR_RESPONSE(response)), |
| details)); |
| } |
| } |
| |
| static void decode_error_response(const char* hex_string, |
| GQuark domain, |
| gint code) { |
| g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new(); |
| g_autoptr(GBytes) message = hex_string_to_bytes(hex_string); |
| g_autoptr(GError) error = nullptr; |
| g_autoptr(FlMethodResponse) response = |
| fl_method_codec_decode_response(FL_METHOD_CODEC(codec), message, &error); |
| EXPECT_EQ(response, nullptr); |
| EXPECT_TRUE(g_error_matches(error, domain, code)); |
| } |
| |
| TEST(FlStandardMethodCodecTest, EncodeMethodCallNullptrArgs) { |
| g_autofree gchar* hex_string = encode_method_call("hello", nullptr); |
| EXPECT_STREQ(hex_string, "070568656c6c6f00"); |
| } |
| |
| TEST(FlStandardMethodCodecTest, EncodeMethodCallNullArgs) { |
| g_autoptr(FlValue) value = fl_value_new_null(); |
| g_autofree gchar* hex_string = encode_method_call("hello", value); |
| EXPECT_STREQ(hex_string, "070568656c6c6f00"); |
| } |
| |
| TEST(FlStandardMethodCodecTest, EncodeMethodCallStringArgs) { |
| g_autoptr(FlValue) args = fl_value_new_string("world"); |
| g_autofree gchar* hex_string = encode_method_call("hello", args); |
| EXPECT_STREQ(hex_string, "070568656c6c6f0705776f726c64"); |
| } |
| |
| TEST(FlStandardMethodCodecTest, EncodeMethodCallListArgs) { |
| g_autoptr(FlValue) args = fl_value_new_list(); |
| fl_value_append_take(args, fl_value_new_string("count")); |
| fl_value_append_take(args, fl_value_new_int(42)); |
| g_autofree gchar* hex_string = encode_method_call("hello", args); |
| EXPECT_STREQ(hex_string, "070568656c6c6f0c020705636f756e74032a000000"); |
| } |
| |
| TEST(FlStandardMethodCodecTest, DecodeMethodCallNullArgs) { |
| g_autofree gchar* name = nullptr; |
| g_autoptr(FlValue) args = nullptr; |
| decode_method_call("070568656c6c6f00", &name, &args); |
| EXPECT_STREQ(name, "hello"); |
| ASSERT_EQ(fl_value_get_type(args), FL_VALUE_TYPE_NULL); |
| } |
| |
| TEST(FlStandardMethodCodecTest, DecodeMethodCallStringArgs) { |
| g_autofree gchar* name = nullptr; |
| g_autoptr(FlValue) args = nullptr; |
| decode_method_call("070568656c6c6f0705776f726c64", &name, &args); |
| EXPECT_STREQ(name, "hello"); |
| ASSERT_EQ(fl_value_get_type(args), FL_VALUE_TYPE_STRING); |
| EXPECT_STREQ(fl_value_get_string(args), "world"); |
| } |
| |
| TEST(FlStandardMethodCodecTest, DecodeMethodCallListArgs) { |
| g_autofree gchar* name = nullptr; |
| g_autoptr(FlValue) args = nullptr; |
| decode_method_call("070568656c6c6f0c020705636f756e74032a000000", &name, |
| &args); |
| EXPECT_STREQ(name, "hello"); |
| ASSERT_EQ(fl_value_get_type(args), FL_VALUE_TYPE_LIST); |
| EXPECT_EQ(fl_value_get_length(args), static_cast<size_t>(2)); |
| |
| FlValue* arg0 = fl_value_get_list_value(args, 0); |
| ASSERT_EQ(fl_value_get_type(arg0), FL_VALUE_TYPE_STRING); |
| EXPECT_STREQ(fl_value_get_string(arg0), "count"); |
| |
| FlValue* arg1 = fl_value_get_list_value(args, 1); |
| ASSERT_EQ(fl_value_get_type(arg1), FL_VALUE_TYPE_INT); |
| EXPECT_EQ(fl_value_get_int(arg1), 42); |
| } |
| |
| TEST(FlStandardMethodCodecTest, DecodeMethodCallNoData) { |
| decode_error_method_call("", FL_MESSAGE_CODEC_ERROR, |
| FL_MESSAGE_CODEC_ERROR_OUT_OF_DATA); |
| } |
| |
| TEST(FlStandardMethodCodecTest, DecodeMethodCallNullMethodName) { |
| decode_error_method_call("000000", FL_MESSAGE_CODEC_ERROR, |
| FL_MESSAGE_CODEC_ERROR_FAILED); |
| } |
| |
| TEST(FlStandardMethodCodecTest, DecodeMethodCallMissingArgs) { |
| decode_error_method_call("070568656c6c6f", FL_MESSAGE_CODEC_ERROR, |
| FL_MESSAGE_CODEC_ERROR_OUT_OF_DATA); |
| } |
| |
| TEST(FlStandardMethodCodecTest, EncodeSuccessEnvelopeNullptr) { |
| g_autofree gchar* hex_string = encode_success_envelope(nullptr); |
| EXPECT_STREQ(hex_string, "0000"); |
| } |
| |
| TEST(FlStandardMethodCodecTest, EncodeSuccessEnvelopeNull) { |
| g_autoptr(FlValue) result = fl_value_new_null(); |
| g_autofree gchar* hex_string = encode_success_envelope(result); |
| EXPECT_STREQ(hex_string, "0000"); |
| } |
| |
| TEST(FlStandardMethodCodecTest, EncodeSuccessEnvelopeString) { |
| g_autoptr(FlValue) result = fl_value_new_string("hello"); |
| g_autofree gchar* hex_string = encode_success_envelope(result); |
| EXPECT_STREQ(hex_string, "00070568656c6c6f"); |
| } |
| |
| TEST(FlStandardMethodCodecTest, EncodeSuccessEnvelopeList) { |
| g_autoptr(FlValue) result = fl_value_new_list(); |
| fl_value_append_take(result, fl_value_new_string("count")); |
| fl_value_append_take(result, fl_value_new_int(42)); |
| g_autofree gchar* hex_string = encode_success_envelope(result); |
| EXPECT_STREQ(hex_string, "000c020705636f756e74032a000000"); |
| } |
| |
| TEST(FlStandardMethodCodecTest, EncodeErrorEnvelopeEmptyCode) { |
| g_autofree gchar* hex_string = encode_error_envelope("", nullptr, nullptr); |
| EXPECT_STREQ(hex_string, "0107000000"); |
| } |
| |
| TEST(FlStandardMethodCodecTest, EncodeErrorEnvelopeNonMessageOrDetails) { |
| g_autofree gchar* hex_string = |
| encode_error_envelope("error", nullptr, nullptr); |
| EXPECT_STREQ(hex_string, "0107056572726f720000"); |
| } |
| |
| TEST(FlStandardMethodCodecTest, EncodeErrorEnvelopeMessage) { |
| g_autofree gchar* hex_string = |
| encode_error_envelope("error", "message", nullptr); |
| EXPECT_STREQ(hex_string, "0107056572726f7207076d65737361676500"); |
| } |
| |
| TEST(FlStandardMethodCodecTest, EncodeErrorEnvelopeDetails) { |
| g_autoptr(FlValue) details = fl_value_new_list(); |
| fl_value_append_take(details, fl_value_new_string("count")); |
| fl_value_append_take(details, fl_value_new_int(42)); |
| g_autofree gchar* hex_string = |
| encode_error_envelope("error", nullptr, details); |
| EXPECT_STREQ(hex_string, "0107056572726f72000c020705636f756e74032a000000"); |
| } |
| |
| TEST(FlStandardMethodCodecTest, EncodeErrorEnvelopeMessageAndDetails) { |
| g_autoptr(FlValue) details = fl_value_new_list(); |
| fl_value_append_take(details, fl_value_new_string("count")); |
| fl_value_append_take(details, fl_value_new_int(42)); |
| g_autofree gchar* hex_string = |
| encode_error_envelope("error", "message", details); |
| EXPECT_STREQ( |
| hex_string, |
| "0107056572726f7207076d6573736167650c020705636f756e74032a000000"); |
| } |
| |
| TEST(FlStandardMethodCodecTest, DecodeResponseSuccessNull) { |
| g_autoptr(FlValue) result = fl_value_new_null(); |
| decode_response_with_success("0000", result); |
| } |
| |
| TEST(FlStandardMethodCodecTest, DecodeResponseSuccessString) { |
| g_autoptr(FlValue) result = fl_value_new_string("hello"); |
| decode_response_with_success("00070568656c6c6f", result); |
| } |
| |
| TEST(FlStandardMethodCodecTest, DecodeResponseSuccessList) { |
| g_autoptr(FlValue) result = fl_value_new_list(); |
| fl_value_append_take(result, fl_value_new_string("count")); |
| fl_value_append_take(result, fl_value_new_int(42)); |
| decode_response_with_success("000c020705636f756e74032a000000", result); |
| } |
| |
| TEST(FlStandardMethodCodecTest, DecodeResponseErrorEmptyCode) { |
| decode_response_with_error("0107000000", "", nullptr, nullptr); |
| } |
| |
| TEST(FlStandardMethodCodecTest, DecodeResponseErrorNoMessageOrDetails) { |
| decode_response_with_error("0107056572726f720000", "error", nullptr, nullptr); |
| } |
| |
| TEST(FlStandardMethodCodecTest, DecodeResponseErrorMessage) { |
| decode_response_with_error("0107056572726f7207076d65737361676500", "error", |
| "message", nullptr); |
| } |
| |
| TEST(FlStandardMethodCodecTest, DecodeResponseErrorDetails) { |
| g_autoptr(FlValue) details = fl_value_new_list(); |
| fl_value_append_take(details, fl_value_new_string("count")); |
| fl_value_append_take(details, fl_value_new_int(42)); |
| decode_response_with_error("0107056572726f72000c020705636f756e74032a000000", |
| "error", nullptr, details); |
| } |
| |
| TEST(FlStandardMethodCodecTest, DecodeResponseErrorMessageAndDetails) { |
| g_autoptr(FlValue) details = fl_value_new_list(); |
| fl_value_append_take(details, fl_value_new_string("count")); |
| fl_value_append_take(details, fl_value_new_int(42)); |
| decode_response_with_error( |
| "0107056572726f7207076d6573736167650c020705636f756e74032a000000", "error", |
| "message", details); |
| } |
| |
| TEST(FlStandardMethodCodecTest, DecodeResponseSuccessNoData) { |
| decode_error_response("00", FL_MESSAGE_CODEC_ERROR, |
| FL_MESSAGE_CODEC_ERROR_OUT_OF_DATA); |
| } |
| |
| TEST(FlStandardMethodCodecTest, DecodeResponseSuccessExtraData) { |
| decode_error_response("000000", FL_MESSAGE_CODEC_ERROR, |
| FL_MESSAGE_CODEC_ERROR_FAILED); |
| } |
| |
| TEST(FlStandardMethodCodecTest, DecodeResponseErrorNoData) { |
| decode_error_response("01", FL_MESSAGE_CODEC_ERROR, |
| FL_MESSAGE_CODEC_ERROR_OUT_OF_DATA); |
| } |
| |
| TEST(FlStandardMethodCodecTest, DecodeResponseErrorMissingMessageAndDetails) { |
| decode_error_response("0107056572726f72", FL_MESSAGE_CODEC_ERROR, |
| FL_MESSAGE_CODEC_ERROR_OUT_OF_DATA); |
| } |
| |
| TEST(FlStandardMethodCodecTest, DecodeResponseErrorMissingDetails) { |
| decode_error_response("0107056572726f7200", FL_MESSAGE_CODEC_ERROR, |
| FL_MESSAGE_CODEC_ERROR_OUT_OF_DATA); |
| } |
| |
| TEST(FlStandardMethodCodecTest, DecodeResponseErrorExtraData) { |
| decode_error_response("0107056572726f72000000", FL_MESSAGE_CODEC_ERROR, |
| FL_MESSAGE_CODEC_ERROR_FAILED); |
| } |
| |
| TEST(FlStandardMethodCodecTest, DecodeResponseNotImplemented) { |
| g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new(); |
| g_autoptr(GBytes) message = g_bytes_new(nullptr, 0); |
| g_autoptr(GError) error = nullptr; |
| g_autoptr(FlMethodResponse) response = |
| fl_method_codec_decode_response(FL_METHOD_CODEC(codec), message, &error); |
| ASSERT_NE(response, nullptr); |
| EXPECT_EQ(error, nullptr); |
| EXPECT_TRUE(FL_IS_METHOD_NOT_IMPLEMENTED_RESPONSE(response)); |
| } |
| |
| TEST(FlStandardMethodCodecTest, DecodeResponseUnknownEnvelope) { |
| decode_error_response("02", FL_MESSAGE_CODEC_ERROR, |
| FL_MESSAGE_CODEC_ERROR_FAILED); |
| } |