1 // Copyright 2021 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "src/core/ext/transport/binder/wire_format/wire_writer.h"
16
17 #include <string>
18 #include <utility>
19
20 #include <gtest/gtest.h>
21
22 #include "absl/memory/memory.h"
23
24 #include <grpcpp/impl/grpc_library.h>
25
26 #include "test/core/transport/binder/mock_objects.h"
27 #include "test/core/util/test_config.h"
28
29 namespace grpc_binder {
30
31 using ::testing::Return;
32
33 MATCHER_P(StrEqInt8Ptr, target, "") {
34 return std::string(reinterpret_cast<const char*>(arg), target.size()) ==
35 target;
36 }
37
TEST(WireWriterTest,RpcCall)38 TEST(WireWriterTest, RpcCall) {
39 grpc::internal::GrpcLibrary init_lib;
40 // Required because wire writer uses combiner internally.
41 grpc_core::ExecCtx exec_ctx;
42 auto mock_binder = std::make_unique<MockBinder>();
43 MockBinder& mock_binder_ref = *mock_binder;
44 MockWritableParcel mock_writable_parcel;
45 ON_CALL(mock_binder_ref, GetWritableParcel)
46 .WillByDefault(Return(&mock_writable_parcel));
47 WireWriterImpl wire_writer(std::move(mock_binder));
48
49 auto ExpectWriteByteArray = [&](const std::string& target) {
50 // length
51 EXPECT_CALL(mock_writable_parcel, WriteInt32(target.size()));
52 if (!target.empty()) {
53 // content
54 EXPECT_CALL(mock_writable_parcel,
55 WriteByteArray(StrEqInt8Ptr(target), target.size()));
56 }
57 };
58
59 ::testing::InSequence sequence;
60 int sequence_number = 0;
61
62 {
63 // flag
64 EXPECT_CALL(mock_writable_parcel, WriteInt32(0));
65 // sequence number
66 EXPECT_CALL(mock_writable_parcel, WriteInt32(sequence_number));
67
68 EXPECT_CALL(mock_binder_ref, Transact(BinderTransportTxCode(kFirstCallId)));
69
70 auto tx = std::make_unique<Transaction>(kFirstCallId, /*is_client=*/true);
71 EXPECT_TRUE(wire_writer.RpcCall(std::move(tx)).ok());
72 sequence_number++;
73 grpc_core::ExecCtx::Get()->Flush();
74 }
75 {
76 // flag
77 EXPECT_CALL(mock_writable_parcel, WriteInt32(kFlagPrefix));
78 // sequence number. This is another stream so the sequence number starts
79 // with 0.
80 EXPECT_CALL(mock_writable_parcel, WriteInt32(0));
81
82 EXPECT_CALL(mock_writable_parcel,
83 WriteString(absl::string_view("/example/method/ref")));
84
85 const std::vector<std::pair<std::string, std::string>> kMetadata = {
86 {"", ""},
87 {"", "value"},
88 {"key", ""},
89 {"key", "value"},
90 {"another-key", "another-value"},
91 };
92
93 // Number of metadata
94 EXPECT_CALL(mock_writable_parcel, WriteInt32(kMetadata.size()));
95
96 for (const auto& md : kMetadata) {
97 ExpectWriteByteArray(md.first);
98 ExpectWriteByteArray(md.second);
99 }
100
101 EXPECT_CALL(mock_binder_ref,
102 Transact(BinderTransportTxCode(kFirstCallId + 1)));
103
104 auto tx =
105 std::make_unique<Transaction>(kFirstCallId + 1, /*is_client=*/true);
106 tx->SetPrefix(kMetadata);
107 tx->SetMethodRef("/example/method/ref");
108 EXPECT_TRUE(wire_writer.RpcCall(std::move(tx)).ok());
109 grpc_core::ExecCtx::Get()->Flush();
110 }
111 {
112 // flag
113 EXPECT_CALL(mock_writable_parcel, WriteInt32(kFlagMessageData));
114 // sequence number
115 EXPECT_CALL(mock_writable_parcel, WriteInt32(sequence_number));
116
117 ExpectWriteByteArray("data");
118 EXPECT_CALL(mock_binder_ref, Transact(BinderTransportTxCode(kFirstCallId)));
119
120 auto tx = std::make_unique<Transaction>(kFirstCallId, /*is_client=*/true);
121 tx->SetData("data");
122 EXPECT_TRUE(wire_writer.RpcCall(std::move(tx)).ok());
123 sequence_number++;
124 grpc_core::ExecCtx::Get()->Flush();
125 }
126 {
127 // flag
128 EXPECT_CALL(mock_writable_parcel, WriteInt32(kFlagSuffix));
129 // sequence number
130 EXPECT_CALL(mock_writable_parcel, WriteInt32(sequence_number));
131
132 EXPECT_CALL(mock_binder_ref, Transact(BinderTransportTxCode(kFirstCallId)));
133
134 auto tx = std::make_unique<Transaction>(kFirstCallId, /*is_client=*/true);
135 tx->SetSuffix({});
136 EXPECT_TRUE(wire_writer.RpcCall(std::move(tx)).ok());
137 sequence_number++;
138 grpc_core::ExecCtx::Get()->Flush();
139 }
140 {
141 // flag
142 EXPECT_CALL(mock_writable_parcel,
143 WriteInt32(kFlagPrefix | kFlagMessageData | kFlagSuffix));
144 // sequence number
145 EXPECT_CALL(mock_writable_parcel, WriteInt32(sequence_number));
146
147 EXPECT_CALL(mock_writable_parcel,
148 WriteString(absl::string_view("/example/method/ref")));
149
150 const std::vector<std::pair<std::string, std::string>> kMetadata = {
151 {"", ""},
152 {"", "value"},
153 {"key", ""},
154 {"key", "value"},
155 {"another-key", "another-value"},
156 };
157
158 // Number of metadata
159 EXPECT_CALL(mock_writable_parcel, WriteInt32(kMetadata.size()));
160
161 for (const auto& md : kMetadata) {
162 ExpectWriteByteArray(md.first);
163 ExpectWriteByteArray(md.second);
164 }
165
166 // Empty message data
167 ExpectWriteByteArray("");
168
169 EXPECT_CALL(mock_binder_ref, Transact(BinderTransportTxCode(kFirstCallId)));
170
171 auto tx = std::make_unique<Transaction>(kFirstCallId, /*is_client=*/true);
172 // TODO(waynetu): Implement a helper function that automatically creates
173 // EXPECT_CALL based on the tx object.
174 tx->SetPrefix(kMetadata);
175 tx->SetMethodRef("/example/method/ref");
176 tx->SetData("");
177 tx->SetSuffix({});
178 EXPECT_TRUE(wire_writer.RpcCall(std::move(tx)).ok());
179 sequence_number++;
180 grpc_core::ExecCtx::Get()->Flush();
181 }
182
183 // Really large message
184 {
185 EXPECT_CALL(mock_writable_parcel,
186 WriteInt32(kFlagMessageData | kFlagMessageDataIsPartial));
187 EXPECT_CALL(mock_writable_parcel, WriteInt32(0));
188 ExpectWriteByteArray(std::string(WireWriterImpl::kBlockSize, 'a'));
189 EXPECT_CALL(mock_writable_parcel, GetDataSize)
190 .WillOnce(Return(WireWriterImpl::kBlockSize));
191 EXPECT_CALL(mock_binder_ref,
192 Transact(BinderTransportTxCode(kFirstCallId + 2)));
193
194 EXPECT_CALL(mock_writable_parcel,
195 WriteInt32(kFlagMessageData | kFlagMessageDataIsPartial));
196 EXPECT_CALL(mock_writable_parcel, WriteInt32(1));
197 ExpectWriteByteArray(std::string(WireWriterImpl::kBlockSize, 'a'));
198 EXPECT_CALL(mock_writable_parcel, GetDataSize)
199 .WillOnce(Return(WireWriterImpl::kBlockSize));
200 EXPECT_CALL(mock_binder_ref,
201 Transact(BinderTransportTxCode(kFirstCallId + 2)));
202
203 EXPECT_CALL(mock_writable_parcel, WriteInt32(kFlagMessageData));
204 EXPECT_CALL(mock_writable_parcel, WriteInt32(2));
205 ExpectWriteByteArray("a");
206 EXPECT_CALL(mock_writable_parcel, GetDataSize).WillOnce(Return(1));
207 EXPECT_CALL(mock_binder_ref,
208 Transact(BinderTransportTxCode(kFirstCallId + 2)));
209
210 // Use a new stream.
211 auto tx =
212 std::make_unique<Transaction>(kFirstCallId + 2, /*is_client=*/true);
213 tx->SetData(std::string(2 * WireWriterImpl::kBlockSize + 1, 'a'));
214 EXPECT_TRUE(wire_writer.RpcCall(std::move(tx)).ok());
215 grpc_core::ExecCtx::Get()->Flush();
216 }
217 // Really large message with metadata
218 {
219 EXPECT_CALL(
220 mock_writable_parcel,
221 WriteInt32(kFlagPrefix | kFlagMessageData | kFlagMessageDataIsPartial));
222 EXPECT_CALL(mock_writable_parcel, WriteInt32(0));
223 EXPECT_CALL(mock_writable_parcel, WriteString(absl::string_view("123")));
224 EXPECT_CALL(mock_writable_parcel, WriteInt32(0));
225 ExpectWriteByteArray(std::string(WireWriterImpl::kBlockSize, 'a'));
226 EXPECT_CALL(mock_writable_parcel, GetDataSize)
227 .WillOnce(Return(WireWriterImpl::kBlockSize));
228 EXPECT_CALL(mock_binder_ref,
229 Transact(BinderTransportTxCode(kFirstCallId + 3)));
230
231 EXPECT_CALL(mock_writable_parcel,
232 WriteInt32(kFlagMessageData | kFlagMessageDataIsPartial));
233 EXPECT_CALL(mock_writable_parcel, WriteInt32(1));
234 ExpectWriteByteArray(std::string(WireWriterImpl::kBlockSize, 'a'));
235 EXPECT_CALL(mock_writable_parcel, GetDataSize)
236 .WillOnce(Return(WireWriterImpl::kBlockSize));
237 EXPECT_CALL(mock_binder_ref,
238 Transact(BinderTransportTxCode(kFirstCallId + 3)));
239
240 EXPECT_CALL(mock_writable_parcel,
241 WriteInt32(kFlagMessageData | kFlagSuffix));
242 EXPECT_CALL(mock_writable_parcel, WriteInt32(2));
243 ExpectWriteByteArray("a");
244 EXPECT_CALL(mock_writable_parcel, GetDataSize).WillOnce(Return(1));
245 EXPECT_CALL(mock_binder_ref,
246 Transact(BinderTransportTxCode(kFirstCallId + 3)));
247
248 // Use a new stream.
249 auto tx =
250 std::make_unique<Transaction>(kFirstCallId + 3, /*is_client=*/true);
251 tx->SetPrefix({});
252 tx->SetMethodRef("123");
253 tx->SetData(std::string(2 * WireWriterImpl::kBlockSize + 1, 'a'));
254 tx->SetSuffix({});
255 EXPECT_TRUE(wire_writer.RpcCall(std::move(tx)).ok());
256 grpc_core::ExecCtx::Get()->Flush();
257 }
258 grpc_core::ExecCtx::Get()->Flush();
259 }
260
261 } // namespace grpc_binder
262
main(int argc,char ** argv)263 int main(int argc, char** argv) {
264 ::testing::InitGoogleTest(&argc, argv);
265 grpc::testing::TestEnvironment env(&argc, argv);
266 return RUN_ALL_TESTS();
267 }
268