Flutter Engine
standard_method_codec_unittests.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/common/client_wrapper/include/flutter/standard_method_codec.h"
6 
7 #include "flutter/shell/platform/common/client_wrapper/include/flutter/method_result_functions.h"
8 #include "flutter/shell/platform/common/client_wrapper/testing/test_codec_extensions.h"
9 #include "gtest/gtest.h"
10 
11 namespace flutter {
12 
13 namespace {
14 
15 // Returns true if the given method calls have the same method name, and their
16 // arguments have equivalent values.
17 bool MethodCallsAreEqual(const MethodCall<>& a, const MethodCall<>& b) {
18  if (a.method_name() != b.method_name()) {
19  return false;
20  }
21  // Treat nullptr and Null as equivalent.
22  if ((!a.arguments() || a.arguments()->IsNull()) &&
23  (!b.arguments() || b.arguments()->IsNull())) {
24  return true;
25  }
26  // If only one is nullptr, fail early rather than throw below.
27  if (!a.arguments() || !b.arguments()) {
28  return false;
29  }
30  return *a.arguments() == *b.arguments();
31 }
32 
33 } // namespace
34 
35 TEST(StandardMethodCodec, GetInstanceCachesInstance) {
36  const StandardMethodCodec& codec_a =
38  const StandardMethodCodec& codec_b =
40  EXPECT_EQ(&codec_a, &codec_b);
41 }
42 
43 TEST(StandardMethodCodec, HandlesMethodCallsWithNullArguments) {
45  MethodCall<> call("hello", nullptr);
46  auto encoded = codec.EncodeMethodCall(call);
47  ASSERT_NE(encoded.get(), nullptr);
48  std::unique_ptr<MethodCall<>> decoded = codec.DecodeMethodCall(*encoded);
49  ASSERT_NE(decoded.get(), nullptr);
50  EXPECT_TRUE(MethodCallsAreEqual(call, *decoded));
51 }
52 
53 TEST(StandardMethodCodec, HandlesMethodCallsWithArgument) {
55  MethodCall<> call("hello", std::make_unique<EncodableValue>(EncodableList{
56  EncodableValue(42),
57  EncodableValue("world"),
58  }));
59  auto encoded = codec.EncodeMethodCall(call);
60  ASSERT_NE(encoded.get(), nullptr);
61  std::unique_ptr<MethodCall<>> decoded = codec.DecodeMethodCall(*encoded);
62  ASSERT_NE(decoded.get(), nullptr);
63  EXPECT_TRUE(MethodCallsAreEqual(call, *decoded));
64 }
65 
66 TEST(StandardMethodCodec, HandlesSuccessEnvelopesWithNullResult) {
68  auto encoded = codec.EncodeSuccessEnvelope();
69  ASSERT_NE(encoded.get(), nullptr);
70  std::vector<uint8_t> bytes = {0x00, 0x00};
71  EXPECT_EQ(*encoded, bytes);
72 
73  bool decoded_successfully = false;
74  MethodResultFunctions<> result_handler(
75  [&decoded_successfully](const EncodableValue* result) {
76  decoded_successfully = true;
77  EXPECT_EQ(result, nullptr);
78  },
79  nullptr, nullptr);
80  codec.DecodeAndProcessResponseEnvelope(encoded->data(), encoded->size(),
81  &result_handler);
82  EXPECT_TRUE(decoded_successfully);
83 }
84 
85 TEST(StandardMethodCodec, HandlesSuccessEnvelopesWithResult) {
88  auto encoded = codec.EncodeSuccessEnvelope(&result);
89  ASSERT_NE(encoded.get(), nullptr);
90  std::vector<uint8_t> bytes = {0x00, 0x03, 0x2a, 0x00, 0x00, 0x00};
91  EXPECT_EQ(*encoded, bytes);
92 
93  bool decoded_successfully = false;
94  MethodResultFunctions<> result_handler(
95  [&decoded_successfully](const EncodableValue* result) {
96  decoded_successfully = true;
97  EXPECT_EQ(std::get<int32_t>(*result), 42);
98  },
99  nullptr, nullptr);
100  codec.DecodeAndProcessResponseEnvelope(encoded->data(), encoded->size(),
101  &result_handler);
102  EXPECT_TRUE(decoded_successfully);
103 }
104 
105 TEST(StandardMethodCodec, HandlesErrorEnvelopesWithNulls) {
107  auto encoded = codec.EncodeErrorEnvelope("errorCode");
108  ASSERT_NE(encoded.get(), nullptr);
109  std::vector<uint8_t> bytes = {0x01, 0x07, 0x09, 0x65, 0x72, 0x72, 0x6f,
110  0x72, 0x43, 0x6f, 0x64, 0x65, 0x00, 0x00};
111  EXPECT_EQ(*encoded, bytes);
112 
113  bool decoded_successfully = false;
114  MethodResultFunctions<> result_handler(
115  nullptr,
116  [&decoded_successfully](const std::string& code,
117  const std::string& message,
118  const EncodableValue* details) {
119  decoded_successfully = true;
120  EXPECT_EQ(code, "errorCode");
121  EXPECT_EQ(message, "");
122  EXPECT_EQ(details, nullptr);
123  },
124  nullptr);
125  codec.DecodeAndProcessResponseEnvelope(encoded->data(), encoded->size(),
126  &result_handler);
127  EXPECT_TRUE(decoded_successfully);
128 }
129 
130 TEST(StandardMethodCodec, HandlesErrorEnvelopesWithDetails) {
133  EncodableValue("a"),
134  EncodableValue(42),
135  });
136  auto encoded =
137  codec.EncodeErrorEnvelope("errorCode", "something failed", &details);
138  ASSERT_NE(encoded.get(), nullptr);
139  std::vector<uint8_t> bytes = {
140  0x01, 0x07, 0x09, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f,
141  0x64, 0x65, 0x07, 0x10, 0x73, 0x6f, 0x6d, 0x65, 0x74, 0x68,
142  0x69, 0x6e, 0x67, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64,
143  0x0c, 0x02, 0x07, 0x01, 0x61, 0x03, 0x2a, 0x00, 0x00, 0x00,
144  };
145  EXPECT_EQ(*encoded, bytes);
146 
147  bool decoded_successfully = false;
148  MethodResultFunctions<> result_handler(
149  nullptr,
150  [&decoded_successfully](const std::string& code,
151  const std::string& message,
152  const EncodableValue* details) {
153  decoded_successfully = true;
154  EXPECT_EQ(code, "errorCode");
155  EXPECT_EQ(message, "something failed");
156  const auto* details_list = std::get_if<EncodableList>(details);
157  ASSERT_NE(details_list, nullptr);
158  EXPECT_EQ(std::get<std::string>((*details_list)[0]), "a");
159  EXPECT_EQ(std::get<int32_t>((*details_list)[1]), 42);
160  },
161  nullptr);
162  codec.DecodeAndProcessResponseEnvelope(encoded->data(), encoded->size(),
163  &result_handler);
164  EXPECT_TRUE(decoded_successfully);
165 }
166 
167 TEST(StandardMethodCodec, HandlesCustomTypeArguments) {
170  Point point(7, 9);
171  MethodCall<> call(
172  "hello", std::make_unique<EncodableValue>(CustomEncodableValue(point)));
173  auto encoded = codec.EncodeMethodCall(call);
174  ASSERT_NE(encoded.get(), nullptr);
175  std::unique_ptr<MethodCall<>> decoded = codec.DecodeMethodCall(*encoded);
176  ASSERT_NE(decoded.get(), nullptr);
177 
178  const Point& decoded_point = std::any_cast<Point>(
179  std::get<CustomEncodableValue>(*decoded->arguments()));
180  EXPECT_EQ(point, decoded_point);
181 };
182 
183 } // namespace flutter
static const PointExtensionSerializer & GetInstance()
GAsyncResult * result
std::unique_ptr< std::vector< uint8_t > > EncodeErrorEnvelope(const std::string &error_code, const std::string &error_message="", const T *error_details=nullptr) const
Definition: method_codec.h:62
bool DecodeAndProcessResponseEnvelope(const uint8_t *response, size_t response_size, MethodResult< T > *result) const
Definition: method_codec.h:75
std::unique_ptr< std::vector< uint8_t > > EncodeMethodCall(const MethodCall< T > &method_call) const
Definition: method_codec.h:48
std::unique_ptr< std::vector< uint8_t > > EncodeSuccessEnvelope(const T *result=nullptr) const
Definition: method_codec.h:55
std::vector< EncodableValue > EncodableList
static const StandardMethodCodec & GetInstance(const StandardCodecSerializer *serializer=nullptr)
std::unique_ptr< MethodCall< T > > DecodeMethodCall(const uint8_t *message, size_t message_size) const
Definition: method_codec.h:32
TEST(DartServiceIsolateTest, CanAddAndRemoveHandles)