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/cpp/client_wrapper/include/flutter/standard_method_codec.h"
6 
7 #include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/method_result_functions.h"
8 #include "flutter/shell/platform/common/cpp/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, HandlesMethodCallsWithNullArguments) {
37  MethodCall<> call("hello", nullptr);
38  auto encoded = codec.EncodeMethodCall(call);
39  ASSERT_NE(encoded.get(), nullptr);
40  std::unique_ptr<MethodCall<>> decoded = codec.DecodeMethodCall(*encoded);
41  ASSERT_NE(decoded.get(), nullptr);
42  EXPECT_TRUE(MethodCallsAreEqual(call, *decoded));
43 }
44 
45 TEST(StandardMethodCodec, HandlesMethodCallsWithArgument) {
47  MethodCall<> call("hello", std::make_unique<EncodableValue>(EncodableList{
48  EncodableValue(42),
49  EncodableValue("world"),
50  }));
51  auto encoded = codec.EncodeMethodCall(call);
52  ASSERT_NE(encoded.get(), nullptr);
53  std::unique_ptr<MethodCall<>> decoded = codec.DecodeMethodCall(*encoded);
54  ASSERT_NE(decoded.get(), nullptr);
55  EXPECT_TRUE(MethodCallsAreEqual(call, *decoded));
56 }
57 
58 TEST(StandardMethodCodec, HandlesSuccessEnvelopesWithNullResult) {
60  auto encoded = codec.EncodeSuccessEnvelope();
61  ASSERT_NE(encoded.get(), nullptr);
62  std::vector<uint8_t> bytes = {0x00, 0x00};
63  EXPECT_EQ(*encoded, bytes);
64 
65  bool decoded_successfully = false;
66  MethodResultFunctions<> result_handler(
67  [&decoded_successfully](const EncodableValue* result) {
68  decoded_successfully = true;
69  EXPECT_EQ(result, nullptr);
70  },
71  nullptr, nullptr);
72  codec.DecodeAndProcessResponseEnvelope(encoded->data(), encoded->size(),
73  &result_handler);
74  EXPECT_TRUE(decoded_successfully);
75 }
76 
77 TEST(StandardMethodCodec, HandlesSuccessEnvelopesWithResult) {
79  EncodableValue result(42);
80  auto encoded = codec.EncodeSuccessEnvelope(&result);
81  ASSERT_NE(encoded.get(), nullptr);
82  std::vector<uint8_t> bytes = {0x00, 0x03, 0x2a, 0x00, 0x00, 0x00};
83  EXPECT_EQ(*encoded, bytes);
84 
85  bool decoded_successfully = false;
86  MethodResultFunctions<> result_handler(
87  [&decoded_successfully](const EncodableValue* result) {
88  decoded_successfully = true;
89  EXPECT_EQ(std::get<int32_t>(*result), 42);
90  },
91  nullptr, nullptr);
92  codec.DecodeAndProcessResponseEnvelope(encoded->data(), encoded->size(),
93  &result_handler);
94  EXPECT_TRUE(decoded_successfully);
95 }
96 
97 TEST(StandardMethodCodec, HandlesErrorEnvelopesWithNulls) {
99  auto encoded = codec.EncodeErrorEnvelope("errorCode");
100  ASSERT_NE(encoded.get(), nullptr);
101  std::vector<uint8_t> bytes = {0x01, 0x07, 0x09, 0x65, 0x72, 0x72, 0x6f,
102  0x72, 0x43, 0x6f, 0x64, 0x65, 0x00, 0x00};
103  EXPECT_EQ(*encoded, bytes);
104 
105  bool decoded_successfully = false;
106  MethodResultFunctions<> result_handler(
107  nullptr,
108  [&decoded_successfully](const std::string& code,
109  const std::string& message,
110  const EncodableValue* details) {
111  decoded_successfully = true;
112  EXPECT_EQ(code, "errorCode");
113  EXPECT_EQ(message, "");
114  EXPECT_EQ(details, nullptr);
115  },
116  nullptr);
117  codec.DecodeAndProcessResponseEnvelope(encoded->data(), encoded->size(),
118  &result_handler);
119  EXPECT_TRUE(decoded_successfully);
120 }
121 
122 TEST(StandardMethodCodec, HandlesErrorEnvelopesWithDetails) {
125  EncodableValue("a"),
126  EncodableValue(42),
127  });
128  auto encoded =
129  codec.EncodeErrorEnvelope("errorCode", "something failed", &details);
130  ASSERT_NE(encoded.get(), nullptr);
131  std::vector<uint8_t> bytes = {
132  0x01, 0x07, 0x09, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f,
133  0x64, 0x65, 0x07, 0x10, 0x73, 0x6f, 0x6d, 0x65, 0x74, 0x68,
134  0x69, 0x6e, 0x67, 0x20, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64,
135  0x0c, 0x02, 0x07, 0x01, 0x61, 0x03, 0x2a, 0x00, 0x00, 0x00,
136  };
137  EXPECT_EQ(*encoded, bytes);
138 
139  bool decoded_successfully = false;
140  MethodResultFunctions<> result_handler(
141  nullptr,
142  [&decoded_successfully](const std::string& code,
143  const std::string& message,
144  const EncodableValue* details) {
145  decoded_successfully = true;
146  EXPECT_EQ(code, "errorCode");
147  EXPECT_EQ(message, "something failed");
148  const auto* details_list = std::get_if<EncodableList>(details);
149  ASSERT_NE(details_list, nullptr);
150  EXPECT_EQ(std::get<std::string>((*details_list)[0]), "a");
151  EXPECT_EQ(std::get<int32_t>((*details_list)[1]), 42);
152  },
153  nullptr);
154  codec.DecodeAndProcessResponseEnvelope(encoded->data(), encoded->size(),
155  &result_handler);
156  EXPECT_TRUE(decoded_successfully);
157 }
158 
159 TEST(StandardMethodCodec, HandlesCustomTypeArguments) {
162  Point point(7, 9);
163  MethodCall<> call(
164  "hello", std::make_unique<EncodableValue>(CustomEncodableValue(point)));
165  auto encoded = codec.EncodeMethodCall(call);
166  ASSERT_NE(encoded.get(), nullptr);
167  std::unique_ptr<MethodCall<>> decoded = codec.DecodeMethodCall(*encoded);
168  ASSERT_NE(decoded.get(), nullptr);
169 
170  const Point& decoded_point = std::any_cast<Point>(
171  std::get<CustomEncodableValue>(*decoded->arguments()));
172  EXPECT_EQ(point, decoded_point);
173 };
174 
175 } // namespace flutter
static const PointExtensionSerializer & GetInstance()
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)