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 // Unit-tests for grpc_binder_transport
16 //
17 // Verify that a calls to the perform_stream_op of grpc_binder_transport
18 // transform into the correct sequence of binder transactions.
19 #include "src/core/ext/transport/binder/transport/binder_transport.h"
20
21 #include <memory>
22 #include <string>
23 #include <vector>
24
25 #include <gtest/gtest.h>
26
27 #include "absl/memory/memory.h"
28 #include "absl/strings/match.h"
29 #include "absl/strings/str_join.h"
30
31 #include <grpc/grpc.h>
32 #include <grpcpp/security/binder_security_policy.h>
33
34 #include "src/core/ext/transport/binder/transport/binder_stream.h"
35 #include "src/core/lib/gprpp/notification.h"
36 #include "src/core/lib/resource_quota/resource_quota.h"
37 #include "test/core/transport/binder/mock_objects.h"
38 #include "test/core/util/test_config.h"
39
40 namespace grpc_binder {
41 namespace {
42
43 using ::testing::Expectation;
44 using ::testing::NiceMock;
45 using ::testing::Return;
46
47 class BinderTransportTest : public ::testing::Test {
48 public:
BinderTransportTest()49 BinderTransportTest()
50 : transport_(grpc_create_binder_transport_client(
51 std::make_unique<NiceMock<MockBinder>>(),
52 std::make_shared<
53 grpc::experimental::binder::UntrustedSecurityPolicy>())) {
54 auto* gbt = reinterpret_cast<grpc_binder_transport*>(transport_);
55 gbt->wire_writer = std::make_unique<MockWireWriter>();
56 GRPC_STREAM_REF_INIT(&ref_, 1, nullptr, nullptr, "phony ref");
57 }
58
~BinderTransportTest()59 ~BinderTransportTest() override {
60 grpc_core::ExecCtx exec_ctx;
61 transport_->Orphan();
62 grpc_core::ExecCtx::Get()->Flush();
63 for (grpc_binder_stream* gbs : stream_buffer_) {
64 gbs->~grpc_binder_stream();
65 gpr_free(gbs);
66 }
67 arena_->Destroy();
68 }
69
PerformStreamOp(grpc_binder_stream * gbs,grpc_transport_stream_op_batch * op)70 void PerformStreamOp(grpc_binder_stream* gbs,
71 grpc_transport_stream_op_batch* op) {
72 transport_->filter_stack_transport()->PerformStreamOp(
73 reinterpret_cast<grpc_stream*>(gbs), op);
74 }
75
GetBinderTransport()76 grpc_binder_transport* GetBinderTransport() {
77 return reinterpret_cast<grpc_binder_transport*>(transport_);
78 }
79
InitNewBinderStream()80 grpc_binder_stream* InitNewBinderStream() {
81 grpc_binder_stream* gbs = static_cast<grpc_binder_stream*>(
82 gpr_malloc(transport_->filter_stack_transport()->SizeOfStream()));
83 transport_->filter_stack_transport()->InitStream(
84 reinterpret_cast<grpc_stream*>(gbs), &ref_, nullptr, arena_);
85 stream_buffer_.push_back(gbs);
86 return gbs;
87 }
88
GetWireWriter()89 MockWireWriter& GetWireWriter() {
90 return *reinterpret_cast<MockWireWriter*>(
91 GetBinderTransport()->wire_writer.get());
92 }
93
SetUpTestSuite()94 static void SetUpTestSuite() { grpc_init(); }
TearDownTestSuite()95 static void TearDownTestSuite() { grpc_shutdown(); }
96
97 protected:
98 grpc_core::MemoryAllocator memory_allocator_ =
99 grpc_core::MemoryAllocator(grpc_core::ResourceQuota::Default()
100 ->memory_quota()
101 ->CreateMemoryAllocator("test"));
102 grpc_core::Arena* arena_ =
103 grpc_core::Arena::Create(/* initial_size = */ 1, &memory_allocator_);
104 grpc_core::Transport* transport_;
105 grpc_stream_refcount ref_;
106 std::vector<grpc_binder_stream*> stream_buffer_;
107 };
108
109 void MockCallback(void* arg, grpc_error_handle error);
110
111 class MockGrpcClosure {
112 public:
MockGrpcClosure(grpc_core::Notification * notification=nullptr)113 explicit MockGrpcClosure(grpc_core::Notification* notification = nullptr)
114 : notification_(notification) {
115 GRPC_CLOSURE_INIT(&closure_, MockCallback, this, nullptr);
116 }
117
GetGrpcClosure()118 grpc_closure* GetGrpcClosure() { return &closure_; }
119 MOCK_METHOD(void, Callback, (grpc_error_handle), ());
120
121 grpc_core::Notification* notification_;
122
123 private:
124 grpc_closure closure_;
125 };
126
MockCallback(void * arg,grpc_error_handle error)127 void MockCallback(void* arg, grpc_error_handle error) {
128 MockGrpcClosure* mock_closure = static_cast<MockGrpcClosure*>(arg);
129 mock_closure->Callback(error);
130 if (mock_closure->notification_) {
131 mock_closure->notification_->Notify();
132 }
133 }
134
MetadataString(const Metadata & a)135 std::string MetadataString(const Metadata& a) {
136 return absl::StrCat(
137 "{",
138 absl::StrJoin(
139 a, ", ",
140 [](std::string* out, const std::pair<std::string, std::string>& kv) {
141 out->append(
142 absl::StrCat("\"", kv.first, "\": \"", kv.second, "\""));
143 }),
144 "}");
145 }
146
MetadataEquivalent(Metadata a,Metadata b)147 bool MetadataEquivalent(Metadata a, Metadata b) {
148 std::sort(a.begin(), a.end());
149 std::sort(b.begin(), b.end());
150 return a == b;
151 }
152
153 // Matches with transactions having the desired flag, method_ref,
154 // initial_metadata, and message_data.
155 MATCHER_P4(TransactionMatches, flag, method_ref, initial_metadata, message_data,
156 "") {
157 if (arg->GetFlags() != flag) return false;
158 if (flag & kFlagPrefix) {
159 if (arg->GetMethodRef() != method_ref) {
160 printf("METHOD REF NOT EQ: %s %s\n",
161 std::string(arg->GetMethodRef()).c_str(),
162 std::string(method_ref).c_str());
163 return false;
164 }
165 if (!MetadataEquivalent(arg->GetPrefixMetadata(), initial_metadata)) {
166 printf("METADATA NOT EQUIVALENT: %s %s\n",
167 MetadataString(arg->GetPrefixMetadata()).c_str(),
168 MetadataString(initial_metadata).c_str());
169 return false;
170 }
171 }
172 if (flag & kFlagMessageData) {
173 if (arg->GetMessageData() != message_data) return false;
174 }
175 return true;
176 }
177
178 // Matches with grpc_error having error message containing |msg|.
179 MATCHER_P(GrpcErrorMessageContains, msg, "") {
180 return absl::StrContains(grpc_core::StatusToString(arg), msg);
181 }
182
183 namespace {
184 class MetadataEncoder {
185 public:
Encode(const grpc_core::Slice & key,const grpc_core::Slice & value)186 void Encode(const grpc_core::Slice& key, const grpc_core::Slice& value) {
187 metadata_.emplace_back(std::string(key.as_string_view()),
188 std::string(value.as_string_view()));
189 }
190
191 template <typename Which>
Encode(Which,const typename Which::ValueType & value)192 void Encode(Which, const typename Which::ValueType& value) {
193 metadata_.emplace_back(
194 std::string(Which::key()),
195 // NOLINTNEXTLINE(google-readability-casting)
196 std::string(grpc_core::Slice(Which::Encode(value)).as_string_view()));
197 }
198
metadata() const199 const Metadata& metadata() const { return metadata_; }
200
201 private:
202 Metadata metadata_;
203 };
204 } // namespace
205
206 // Verify that the lower-level metadata has the same content as the gRPC
207 // metadata.
VerifyMetadataEqual(const Metadata & md,const grpc_metadata_batch & grpc_md)208 void VerifyMetadataEqual(const Metadata& md,
209 const grpc_metadata_batch& grpc_md) {
210 MetadataEncoder encoder;
211 grpc_md.Encode(&encoder);
212 EXPECT_TRUE(MetadataEquivalent(encoder.metadata(), md));
213 }
214
215 // RAII helper classes for constructing gRPC metadata and receiving callbacks.
216 struct MakeSendInitialMetadata {
MakeSendInitialMetadatagrpc_binder::__anon521925940111::MakeSendInitialMetadata217 MakeSendInitialMetadata(const Metadata& initial_metadata,
218 const std::string& method_ref,
219 grpc_transport_stream_op_batch* op) {
220 for (const auto& md : initial_metadata) {
221 const std::string& key = md.first;
222 const std::string& value = md.second;
223 grpc_initial_metadata.Append(
224 key, grpc_core::Slice::FromCopiedString(value),
225 [](absl::string_view, const grpc_core::Slice&) { abort(); });
226 }
227 if (!method_ref.empty()) {
228 grpc_initial_metadata.Set(grpc_core::HttpPathMetadata(),
229 grpc_core::Slice::FromCopiedString(method_ref));
230 }
231 op->send_initial_metadata = true;
232 op->payload->send_initial_metadata.send_initial_metadata =
233 &grpc_initial_metadata;
234 }
~MakeSendInitialMetadatagrpc_binder::__anon521925940111::MakeSendInitialMetadata235 ~MakeSendInitialMetadata() {}
236
237 grpc_core::MemoryAllocator memory_allocator =
238 grpc_core::MemoryAllocator(grpc_core::ResourceQuota::Default()
239 ->memory_quota()
240 ->CreateMemoryAllocator("test"));
241 grpc_core::ScopedArenaPtr arena =
242 grpc_core::MakeScopedArena(1024, &memory_allocator);
243 grpc_metadata_batch grpc_initial_metadata;
244 };
245
246 struct MakeSendMessage {
MakeSendMessagegrpc_binder::__anon521925940111::MakeSendMessage247 MakeSendMessage(const std::string& message,
248 grpc_transport_stream_op_batch* op) {
249 send_stream.Append(grpc_core::Slice::FromCopiedString(message));
250
251 op->send_message = true;
252 op->payload->send_message.send_message = &send_stream;
253 }
254
255 grpc_core::SliceBuffer send_stream;
256 };
257
258 struct MakeSendTrailingMetadata {
MakeSendTrailingMetadatagrpc_binder::__anon521925940111::MakeSendTrailingMetadata259 explicit MakeSendTrailingMetadata(const Metadata& trailing_metadata,
260 grpc_transport_stream_op_batch* op) {
261 EXPECT_TRUE(trailing_metadata.empty());
262
263 op->send_trailing_metadata = true;
264 op->payload->send_trailing_metadata.send_trailing_metadata =
265 &grpc_trailing_metadata;
266 }
267
268 grpc_core::MemoryAllocator memory_allocator =
269 grpc_core::MemoryAllocator(grpc_core::ResourceQuota::Default()
270 ->memory_quota()
271 ->CreateMemoryAllocator("test"));
272 grpc_core::ScopedArenaPtr arena =
273 grpc_core::MakeScopedArena(1024, &memory_allocator);
274 grpc_metadata_batch grpc_trailing_metadata;
275 };
276
277 struct MakeRecvInitialMetadata {
MakeRecvInitialMetadatagrpc_binder::__anon521925940111::MakeRecvInitialMetadata278 explicit MakeRecvInitialMetadata(grpc_transport_stream_op_batch* op,
279 Expectation* call_before = nullptr)
280 : ready(¬ification) {
281 op->recv_initial_metadata = true;
282 op->payload->recv_initial_metadata.recv_initial_metadata =
283 &grpc_initial_metadata;
284 op->payload->recv_initial_metadata.recv_initial_metadata_ready =
285 ready.GetGrpcClosure();
286 if (call_before) {
287 EXPECT_CALL(ready, Callback).After(*call_before);
288 } else {
289 EXPECT_CALL(ready, Callback);
290 }
291 }
292
~MakeRecvInitialMetadatagrpc_binder::__anon521925940111::MakeRecvInitialMetadata293 ~MakeRecvInitialMetadata() {}
294
295 MockGrpcClosure ready;
296 grpc_core::MemoryAllocator memory_allocator =
297 grpc_core::MemoryAllocator(grpc_core::ResourceQuota::Default()
298 ->memory_quota()
299 ->CreateMemoryAllocator("test"));
300 grpc_core::ScopedArenaPtr arena =
301 grpc_core::MakeScopedArena(1024, &memory_allocator);
302 grpc_metadata_batch grpc_initial_metadata;
303 grpc_core::Notification notification;
304 };
305
306 struct MakeRecvMessage {
MakeRecvMessagegrpc_binder::__anon521925940111::MakeRecvMessage307 explicit MakeRecvMessage(grpc_transport_stream_op_batch* op,
308 Expectation* call_before = nullptr)
309 : ready(¬ification) {
310 op->recv_message = true;
311 op->payload->recv_message.recv_message = &grpc_message;
312 op->payload->recv_message.recv_message_ready = ready.GetGrpcClosure();
313 if (call_before) {
314 EXPECT_CALL(ready, Callback).After(*call_before);
315 } else {
316 EXPECT_CALL(ready, Callback);
317 }
318 }
319
320 MockGrpcClosure ready;
321 grpc_core::Notification notification;
322 absl::optional<grpc_core::SliceBuffer> grpc_message;
323 };
324
325 struct MakeRecvTrailingMetadata {
MakeRecvTrailingMetadatagrpc_binder::__anon521925940111::MakeRecvTrailingMetadata326 explicit MakeRecvTrailingMetadata(grpc_transport_stream_op_batch* op,
327 Expectation* call_before = nullptr)
328 : ready(¬ification) {
329 op->recv_trailing_metadata = true;
330 op->payload->recv_trailing_metadata.recv_trailing_metadata =
331 &grpc_trailing_metadata;
332 op->payload->recv_trailing_metadata.recv_trailing_metadata_ready =
333 ready.GetGrpcClosure();
334 if (call_before) {
335 EXPECT_CALL(ready, Callback).After(*call_before);
336 } else {
337 EXPECT_CALL(ready, Callback);
338 }
339 }
340
~MakeRecvTrailingMetadatagrpc_binder::__anon521925940111::MakeRecvTrailingMetadata341 ~MakeRecvTrailingMetadata() {}
342
343 MockGrpcClosure ready;
344 grpc_core::MemoryAllocator memory_allocator =
345 grpc_core::MemoryAllocator(grpc_core::ResourceQuota::Default()
346 ->memory_quota()
347 ->CreateMemoryAllocator("test"));
348 grpc_core::ScopedArenaPtr arena =
349 grpc_core::MakeScopedArena(1024, &memory_allocator);
350 grpc_metadata_batch grpc_trailing_metadata;
351 grpc_core::Notification notification;
352 };
353
354 const Metadata kDefaultMetadata = {
355 {"", ""},
356 {"", "value"},
357 {"key", ""},
358 {"key", "value"},
359 };
360
361 constexpr char kDefaultMethodRef[] = "/some/path";
362 constexpr char kDefaultMessage[] = "binder transport message";
363 constexpr int kDefaultStatus = 0x1234;
364
AppendMethodRef(const Metadata & md,const std::string & method_ref)365 Metadata AppendMethodRef(const Metadata& md, const std::string& method_ref) {
366 Metadata result = md;
367 result.emplace_back(":path", method_ref);
368 return result;
369 }
370
AppendStatus(const Metadata & md,int status)371 Metadata AppendStatus(const Metadata& md, int status) {
372 Metadata result = md;
373 result.emplace_back("grpc-status", std::to_string(status));
374 return result;
375 }
376
377 } // namespace
378
TEST_F(BinderTransportTest,CreateBinderTransport)379 TEST_F(BinderTransportTest, CreateBinderTransport) {
380 EXPECT_NE(transport_, nullptr);
381 }
382
TEST_F(BinderTransportTest,TransactionIdIncrement)383 TEST_F(BinderTransportTest, TransactionIdIncrement) {
384 grpc_binder_stream* gbs0 = InitNewBinderStream();
385 EXPECT_EQ(gbs0->t, GetBinderTransport());
386 EXPECT_EQ(gbs0->tx_code, kFirstCallId);
387 grpc_binder_stream* gbs1 = InitNewBinderStream();
388 EXPECT_EQ(gbs1->t, GetBinderTransport());
389 EXPECT_EQ(gbs1->tx_code, kFirstCallId + 1);
390 grpc_binder_stream* gbs2 = InitNewBinderStream();
391 EXPECT_EQ(gbs2->t, GetBinderTransport());
392 EXPECT_EQ(gbs2->tx_code, kFirstCallId + 2);
393 }
394
TEST_F(BinderTransportTest,PerformSendInitialMetadata)395 TEST_F(BinderTransportTest, PerformSendInitialMetadata) {
396 grpc_core::ExecCtx exec_ctx;
397 grpc_binder_stream* gbs = InitNewBinderStream();
398 grpc_transport_stream_op_batch op{};
399 grpc_transport_stream_op_batch_payload payload(nullptr);
400 op.payload = &payload;
401 const Metadata kInitialMetadata = kDefaultMetadata;
402 MakeSendInitialMetadata send_initial_metadata(kInitialMetadata, "", &op);
403 MockGrpcClosure mock_on_complete;
404 op.on_complete = mock_on_complete.GetGrpcClosure();
405
406 ::testing::InSequence sequence;
407 EXPECT_CALL(GetWireWriter(), RpcCall(TransactionMatches(
408 kFlagPrefix, "", kInitialMetadata, "")));
409 EXPECT_CALL(mock_on_complete, Callback);
410
411 PerformStreamOp(gbs, &op);
412 grpc_core::ExecCtx::Get()->Flush();
413 }
414
TEST_F(BinderTransportTest,PerformSendInitialMetadataMethodRef)415 TEST_F(BinderTransportTest, PerformSendInitialMetadataMethodRef) {
416 grpc_core::ExecCtx exec_ctx;
417 grpc_binder_stream* gbs = InitNewBinderStream();
418 grpc_transport_stream_op_batch op{};
419 grpc_transport_stream_op_batch_payload payload(nullptr);
420 op.payload = &payload;
421 const Metadata kInitialMetadata = kDefaultMetadata;
422 const std::string kMethodRef = kDefaultMethodRef;
423 MakeSendInitialMetadata send_initial_metadata(kInitialMetadata, kMethodRef,
424 &op);
425 MockGrpcClosure mock_on_complete;
426 op.on_complete = mock_on_complete.GetGrpcClosure();
427
428 ::testing::InSequence sequence;
429 EXPECT_CALL(GetWireWriter(),
430 RpcCall(TransactionMatches(kFlagPrefix, kMethodRef.substr(1),
431 kInitialMetadata, "")));
432 EXPECT_CALL(mock_on_complete, Callback);
433
434 PerformStreamOp(gbs, &op);
435 grpc_core::ExecCtx::Get()->Flush();
436 }
437
TEST_F(BinderTransportTest,PerformSendMessage)438 TEST_F(BinderTransportTest, PerformSendMessage) {
439 grpc_core::ExecCtx exec_ctx;
440 grpc_binder_stream* gbs = InitNewBinderStream();
441 grpc_transport_stream_op_batch op{};
442 grpc_transport_stream_op_batch_payload payload(nullptr);
443 op.payload = &payload;
444
445 const std::string kMessage = kDefaultMessage;
446 MakeSendMessage send_message(kMessage, &op);
447 MockGrpcClosure mock_on_complete;
448 op.on_complete = mock_on_complete.GetGrpcClosure();
449
450 ::testing::InSequence sequence;
451 EXPECT_CALL(
452 GetWireWriter(),
453 RpcCall(TransactionMatches(kFlagMessageData, "", Metadata{}, kMessage)));
454 EXPECT_CALL(mock_on_complete, Callback);
455
456 PerformStreamOp(gbs, &op);
457 grpc_core::ExecCtx::Get()->Flush();
458 }
459
TEST_F(BinderTransportTest,PerformSendTrailingMetadata)460 TEST_F(BinderTransportTest, PerformSendTrailingMetadata) {
461 grpc_core::ExecCtx exec_ctx;
462 grpc_binder_stream* gbs = InitNewBinderStream();
463 grpc_transport_stream_op_batch op{};
464 grpc_transport_stream_op_batch_payload payload(nullptr);
465 op.payload = &payload;
466 // The wireformat guarantees that suffix metadata will always be empty.
467 // TODO(waynetu): Check whether gRPC can internally add extra trailing
468 // metadata.
469 const Metadata kTrailingMetadata = {};
470 MakeSendTrailingMetadata send_trailing_metadata(kTrailingMetadata, &op);
471 MockGrpcClosure mock_on_complete;
472 op.on_complete = mock_on_complete.GetGrpcClosure();
473
474 ::testing::InSequence sequence;
475 EXPECT_CALL(GetWireWriter(), RpcCall(TransactionMatches(
476 kFlagSuffix, "", kTrailingMetadata, "")));
477 EXPECT_CALL(mock_on_complete, Callback);
478
479 PerformStreamOp(gbs, &op);
480 grpc_core::ExecCtx::Get()->Flush();
481 }
482
TEST_F(BinderTransportTest,PerformSendAll)483 TEST_F(BinderTransportTest, PerformSendAll) {
484 grpc_core::ExecCtx exec_ctx;
485 grpc_binder_stream* gbs = InitNewBinderStream();
486 grpc_transport_stream_op_batch op{};
487 grpc_transport_stream_op_batch_payload payload(nullptr);
488 op.payload = &payload;
489
490 const Metadata kInitialMetadata = kDefaultMetadata;
491 const std::string kMethodRef = kDefaultMethodRef;
492 MakeSendInitialMetadata send_initial_metadata(kInitialMetadata, kMethodRef,
493 &op);
494
495 const std::string kMessage = kDefaultMessage;
496 MakeSendMessage send_message(kMessage, &op);
497
498 // The wireformat guarantees that suffix metadata will always be empty.
499 // TODO(waynetu): Check whether gRPC can internally add extra trailing
500 // metadata.
501 const Metadata kTrailingMetadata = {};
502 MakeSendTrailingMetadata send_trailing_metadata(kTrailingMetadata, &op);
503
504 MockGrpcClosure mock_on_complete;
505 op.on_complete = mock_on_complete.GetGrpcClosure();
506
507 ::testing::InSequence sequence;
508 EXPECT_CALL(GetWireWriter(),
509 RpcCall(TransactionMatches(
510 kFlagPrefix | kFlagMessageData | kFlagSuffix,
511 kMethodRef.substr(1), kInitialMetadata, kMessage)));
512 EXPECT_CALL(mock_on_complete, Callback);
513
514 PerformStreamOp(gbs, &op);
515 grpc_core::ExecCtx::Get()->Flush();
516 }
517
TEST_F(BinderTransportTest,PerformRecvInitialMetadata)518 TEST_F(BinderTransportTest, PerformRecvInitialMetadata) {
519 grpc_core::ExecCtx exec_ctx;
520 grpc_binder_stream* gbs = InitNewBinderStream();
521 grpc_transport_stream_op_batch op{};
522 grpc_transport_stream_op_batch_payload payload(nullptr);
523 op.payload = &payload;
524
525 MakeRecvInitialMetadata recv_initial_metadata(&op);
526
527 const Metadata kInitialMetadata = kDefaultMetadata;
528 auto* gbt = reinterpret_cast<grpc_binder_transport*>(transport_);
529 gbt->transport_stream_receiver->NotifyRecvInitialMetadata(gbs->tx_code,
530 kInitialMetadata);
531 PerformStreamOp(gbs, &op);
532 grpc_core::ExecCtx::Get()->Flush();
533 recv_initial_metadata.notification.WaitForNotification();
534
535 VerifyMetadataEqual(kInitialMetadata,
536 recv_initial_metadata.grpc_initial_metadata);
537 }
538
TEST_F(BinderTransportTest,PerformRecvInitialMetadataWithMethodRef)539 TEST_F(BinderTransportTest, PerformRecvInitialMetadataWithMethodRef) {
540 grpc_core::ExecCtx exec_ctx;
541 grpc_binder_stream* gbs = InitNewBinderStream();
542 grpc_transport_stream_op_batch op{};
543 grpc_transport_stream_op_batch_payload payload(nullptr);
544 op.payload = &payload;
545
546 MakeRecvInitialMetadata recv_initial_metadata(&op);
547
548 auto* gbt = reinterpret_cast<grpc_binder_transport*>(transport_);
549 const Metadata kInitialMetadataWithMethodRef =
550 AppendMethodRef(kDefaultMetadata, kDefaultMethodRef);
551 gbt->transport_stream_receiver->NotifyRecvInitialMetadata(
552 gbs->tx_code, kInitialMetadataWithMethodRef);
553 PerformStreamOp(gbs, &op);
554 grpc_core::ExecCtx::Get()->Flush();
555 recv_initial_metadata.notification.WaitForNotification();
556
557 VerifyMetadataEqual(kInitialMetadataWithMethodRef,
558 recv_initial_metadata.grpc_initial_metadata);
559 }
560
TEST_F(BinderTransportTest,PerformRecvMessage)561 TEST_F(BinderTransportTest, PerformRecvMessage) {
562 grpc_core::ExecCtx exec_ctx;
563 grpc_binder_stream* gbs = InitNewBinderStream();
564 grpc_transport_stream_op_batch op{};
565 grpc_transport_stream_op_batch_payload payload(nullptr);
566 op.payload = &payload;
567
568 MakeRecvMessage recv_message(&op);
569
570 auto* gbt = reinterpret_cast<grpc_binder_transport*>(transport_);
571 const std::string kMessage = kDefaultMessage;
572 gbt->transport_stream_receiver->NotifyRecvMessage(gbs->tx_code, kMessage);
573
574 PerformStreamOp(gbs, &op);
575 grpc_core::ExecCtx::Get()->Flush();
576 recv_message.notification.WaitForNotification();
577
578 EXPECT_EQ(kMessage, recv_message.grpc_message->JoinIntoString());
579 }
580
TEST_F(BinderTransportTest,PerformRecvTrailingMetadata)581 TEST_F(BinderTransportTest, PerformRecvTrailingMetadata) {
582 grpc_core::ExecCtx exec_ctx;
583 grpc_binder_stream* gbs = InitNewBinderStream();
584 grpc_transport_stream_op_batch op{};
585 grpc_transport_stream_op_batch_payload payload(nullptr);
586 op.payload = &payload;
587
588 MakeRecvTrailingMetadata recv_trailing_metadata(&op);
589
590 const Metadata kTrailingMetadata = kDefaultMetadata;
591 auto* gbt = reinterpret_cast<grpc_binder_transport*>(transport_);
592 constexpr int kStatus = kDefaultStatus;
593 gbt->transport_stream_receiver->NotifyRecvTrailingMetadata(
594 gbs->tx_code, kTrailingMetadata, kStatus);
595 PerformStreamOp(gbs, &op);
596 grpc_core::ExecCtx::Get()->Flush();
597 recv_trailing_metadata.notification.WaitForNotification();
598
599 VerifyMetadataEqual(AppendStatus(kTrailingMetadata, kStatus),
600 recv_trailing_metadata.grpc_trailing_metadata);
601 }
602
TEST_F(BinderTransportTest,PerformRecvAll)603 TEST_F(BinderTransportTest, PerformRecvAll) {
604 grpc_core::ExecCtx exec_ctx;
605 grpc_binder_stream* gbs = InitNewBinderStream();
606 grpc_transport_stream_op_batch op{};
607 grpc_transport_stream_op_batch_payload payload(nullptr);
608 op.payload = &payload;
609
610 MakeRecvInitialMetadata recv_initial_metadata(&op);
611 MakeRecvMessage recv_message(&op);
612 MakeRecvTrailingMetadata recv_trailing_metadata(&op);
613
614 auto* gbt = reinterpret_cast<grpc_binder_transport*>(transport_);
615 const Metadata kInitialMetadataWithMethodRef =
616 AppendMethodRef(kDefaultMetadata, kDefaultMethodRef);
617 gbt->transport_stream_receiver->NotifyRecvInitialMetadata(
618 gbs->tx_code, kInitialMetadataWithMethodRef);
619
620 const std::string kMessage = kDefaultMessage;
621 gbt->transport_stream_receiver->NotifyRecvMessage(gbs->tx_code, kMessage);
622
623 Metadata trailing_metadata = kDefaultMetadata;
624 constexpr int kStatus = kDefaultStatus;
625 gbt->transport_stream_receiver->NotifyRecvTrailingMetadata(
626 gbs->tx_code, trailing_metadata, kStatus);
627 PerformStreamOp(gbs, &op);
628 grpc_core::ExecCtx::Get()->Flush();
629 recv_trailing_metadata.notification.WaitForNotification();
630
631 VerifyMetadataEqual(kInitialMetadataWithMethodRef,
632 recv_initial_metadata.grpc_initial_metadata);
633 trailing_metadata.emplace_back("grpc-status", std::to_string(kStatus));
634 VerifyMetadataEqual(trailing_metadata,
635 recv_trailing_metadata.grpc_trailing_metadata);
636 EXPECT_EQ(kMessage, recv_message.grpc_message->JoinIntoString());
637 }
638
TEST_F(BinderTransportTest,PerformAllOps)639 TEST_F(BinderTransportTest, PerformAllOps) {
640 grpc_core::ExecCtx exec_ctx;
641 grpc_binder_stream* gbs = InitNewBinderStream();
642 grpc_transport_stream_op_batch op{};
643 grpc_transport_stream_op_batch_payload payload(nullptr);
644 op.payload = &payload;
645
646 const Metadata kSendInitialMetadata = kDefaultMetadata;
647 const std::string kMethodRef = kDefaultMethodRef;
648 MakeSendInitialMetadata send_initial_metadata(kSendInitialMetadata,
649 kMethodRef, &op);
650
651 const std::string kSendMessage = kDefaultMessage;
652 MakeSendMessage send_message(kSendMessage, &op);
653
654 // The wireformat guarantees that suffix metadata will always be empty.
655 // TODO(waynetu): Check whether gRPC can internally add extra trailing
656 // metadata.
657 const Metadata kSendTrailingMetadata = {};
658 MakeSendTrailingMetadata send_trailing_metadata(kSendTrailingMetadata, &op);
659
660 MockGrpcClosure mock_on_complete;
661 op.on_complete = mock_on_complete.GetGrpcClosure();
662
663 // TODO(waynetu): Currently, we simply drop the prefix '/' from the :path
664 // argument to obtain the method name. Update the test if this turns out to be
665 // incorrect.
666 EXPECT_CALL(GetWireWriter(),
667 RpcCall(TransactionMatches(
668 kFlagPrefix | kFlagMessageData | kFlagSuffix,
669 kMethodRef.substr(1), kSendInitialMetadata, kSendMessage)));
670 Expectation on_complete = EXPECT_CALL(mock_on_complete, Callback);
671
672 // Recv callbacks can happen after the on_complete callback.
673 MakeRecvInitialMetadata recv_initial_metadata(
674 &op, /* call_before = */ &on_complete);
675 MakeRecvMessage recv_message(&op, /* call_before = */ &on_complete);
676 MakeRecvTrailingMetadata recv_trailing_metadata(
677 &op, /* call_before = */ &on_complete);
678
679 PerformStreamOp(gbs, &op);
680
681 // Flush the execution context to force on_complete to run before recv
682 // callbacks get scheduled.
683 grpc_core::ExecCtx::Get()->Flush();
684
685 auto* gbt = reinterpret_cast<grpc_binder_transport*>(transport_);
686 const Metadata kRecvInitialMetadata =
687 AppendMethodRef(kDefaultMetadata, kDefaultMethodRef);
688 gbt->transport_stream_receiver->NotifyRecvInitialMetadata(
689 gbs->tx_code, kRecvInitialMetadata);
690 const std::string kRecvMessage = kDefaultMessage;
691 gbt->transport_stream_receiver->NotifyRecvMessage(gbs->tx_code, kRecvMessage);
692 const Metadata kRecvTrailingMetadata = kDefaultMetadata;
693 constexpr int kStatus = 0x1234;
694 gbt->transport_stream_receiver->NotifyRecvTrailingMetadata(
695 gbs->tx_code, kRecvTrailingMetadata, kStatus);
696
697 grpc_core::ExecCtx::Get()->Flush();
698 recv_initial_metadata.notification.WaitForNotification();
699 recv_message.notification.WaitForNotification();
700 recv_trailing_metadata.notification.WaitForNotification();
701
702 VerifyMetadataEqual(kRecvInitialMetadata,
703 recv_initial_metadata.grpc_initial_metadata);
704 VerifyMetadataEqual(AppendStatus(kRecvTrailingMetadata, kStatus),
705 recv_trailing_metadata.grpc_trailing_metadata);
706
707 EXPECT_EQ(kRecvMessage, recv_message.grpc_message->JoinIntoString());
708 }
709
TEST_F(BinderTransportTest,WireWriterRpcCallErrorPropagates)710 TEST_F(BinderTransportTest, WireWriterRpcCallErrorPropagates) {
711 grpc_core::ExecCtx exec_ctx;
712 grpc_binder_stream* gbs = InitNewBinderStream();
713
714 MockGrpcClosure mock_on_complete1;
715 MockGrpcClosure mock_on_complete2;
716
717 EXPECT_CALL(GetWireWriter(), RpcCall)
718 .WillOnce(Return(absl::OkStatus()))
719 .WillOnce(Return(absl::InternalError("WireWriter::RpcCall failed")));
720 EXPECT_CALL(mock_on_complete1, Callback(absl::OkStatus()));
721 EXPECT_CALL(mock_on_complete2,
722 Callback(GrpcErrorMessageContains("WireWriter::RpcCall failed")));
723
724 const Metadata kInitialMetadata = {};
725 grpc_transport_stream_op_batch op1{};
726 grpc_transport_stream_op_batch_payload payload1(nullptr);
727 op1.payload = &payload1;
728 MakeSendInitialMetadata send_initial_metadata1(kInitialMetadata, "", &op1);
729 op1.on_complete = mock_on_complete1.GetGrpcClosure();
730
731 grpc_transport_stream_op_batch op2{};
732 grpc_transport_stream_op_batch_payload payload2(nullptr);
733 op2.payload = &payload2;
734 MakeSendInitialMetadata send_initial_metadata2(kInitialMetadata, "", &op2);
735 op2.on_complete = mock_on_complete2.GetGrpcClosure();
736
737 PerformStreamOp(gbs, &op1);
738 PerformStreamOp(gbs, &op2);
739 grpc_core::ExecCtx::Get()->Flush();
740 }
741
742 } // namespace grpc_binder
743
main(int argc,char ** argv)744 int main(int argc, char** argv) {
745 ::testing::InitGoogleTest(&argc, argv);
746 grpc::testing::TestEnvironment env(&argc, argv);
747 return RUN_ALL_TESTS();
748 }
749