1 // Copyright 2016 The Chromium 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 <utility> 6 7 #include "base/bind.h" 8 #include "base/logging.h" 9 #include "base/macros.h" 10 #include "base/message_loop/message_loop.h" 11 #include "base/run_loop.h" 12 #include "base/threading/thread.h" 13 #include "mojo/public/cpp/bindings/associated_binding.h" 14 #include "mojo/public/cpp/bindings/binding.h" 15 #include "mojo/public/interfaces/bindings/tests/test_sync_methods.mojom.h" 16 #include "testing/gtest/include/gtest/gtest.h" 17 18 namespace mojo { 19 namespace test { 20 namespace { 21 22 template <typename... Args> 23 struct LambdaBinder { 24 using CallbackType = base::Callback<void(Args...)>; 25 26 template <typename Func> 27 static void RunLambda(Func func, Args... args) { 28 func(std::move(args)...); 29 } 30 31 template <typename Func> 32 static CallbackType BindLambda(Func func) { 33 return base::Bind(&LambdaBinder::RunLambda<Func>, func); 34 } 35 }; 36 37 class TestSyncCommonImpl { 38 public: 39 TestSyncCommonImpl() {} 40 41 using PingHandler = base::Callback<void(const base::Callback<void()>&)>; 42 using PingBinder = LambdaBinder<const base::Callback<void()>&>; 43 template <typename Func> 44 void set_ping_handler(Func handler) { 45 ping_handler_ = PingBinder::BindLambda(handler); 46 } 47 48 using EchoHandler = 49 base::Callback<void(int32_t, const base::Callback<void(int32_t)>&)>; 50 using EchoBinder = 51 LambdaBinder<int32_t, const base::Callback<void(int32_t)>&>; 52 template <typename Func> 53 void set_echo_handler(Func handler) { 54 echo_handler_ = EchoBinder::BindLambda(handler); 55 } 56 57 using AsyncEchoHandler = 58 base::Callback<void(int32_t, const base::Callback<void(int32_t)>&)>; 59 using AsyncEchoBinder = 60 LambdaBinder<int32_t, const base::Callback<void(int32_t)>&>; 61 template <typename Func> 62 void set_async_echo_handler(Func handler) { 63 async_echo_handler_ = AsyncEchoBinder::BindLambda(handler); 64 } 65 66 using SendInterfaceHandler = base::Callback<void(TestSyncAssociatedPtrInfo)>; 67 using SendInterfaceBinder = LambdaBinder<TestSyncAssociatedPtrInfo>; 68 template <typename Func> 69 void set_send_interface_handler(Func handler) { 70 send_interface_handler_ = SendInterfaceBinder::BindLambda(handler); 71 } 72 73 using SendRequestHandler = base::Callback<void(TestSyncAssociatedRequest)>; 74 using SendRequestBinder = LambdaBinder<TestSyncAssociatedRequest>; 75 template <typename Func> 76 void set_send_request_handler(Func handler) { 77 send_request_handler_ = SendRequestBinder::BindLambda(handler); 78 } 79 80 void PingImpl(const base::Callback<void()>& callback) { 81 if (ping_handler_.is_null()) { 82 callback.Run(); 83 return; 84 } 85 ping_handler_.Run(callback); 86 } 87 void EchoImpl(int32_t value, const base::Callback<void(int32_t)>& callback) { 88 if (echo_handler_.is_null()) { 89 callback.Run(value); 90 return; 91 } 92 echo_handler_.Run(value, callback); 93 } 94 void AsyncEchoImpl(int32_t value, 95 const base::Callback<void(int32_t)>& callback) { 96 if (async_echo_handler_.is_null()) { 97 callback.Run(value); 98 return; 99 } 100 async_echo_handler_.Run(value, callback); 101 } 102 void SendInterfaceImpl(TestSyncAssociatedPtrInfo ptr) { 103 send_interface_handler_.Run(std::move(ptr)); 104 } 105 void SendRequestImpl(TestSyncAssociatedRequest request) { 106 send_request_handler_.Run(std::move(request)); 107 } 108 109 private: 110 PingHandler ping_handler_; 111 EchoHandler echo_handler_; 112 AsyncEchoHandler async_echo_handler_; 113 SendInterfaceHandler send_interface_handler_; 114 SendRequestHandler send_request_handler_; 115 116 DISALLOW_COPY_AND_ASSIGN(TestSyncCommonImpl); 117 }; 118 119 class TestSyncImpl : public TestSync, public TestSyncCommonImpl { 120 public: 121 explicit TestSyncImpl(TestSyncRequest request) 122 : binding_(this, std::move(request)) {} 123 124 // TestSync implementation: 125 void Ping(const PingCallback& callback) override { PingImpl(callback); } 126 void Echo(int32_t value, const EchoCallback& callback) override { 127 EchoImpl(value, callback); 128 } 129 void AsyncEcho(int32_t value, const AsyncEchoCallback& callback) override { 130 AsyncEchoImpl(value, callback); 131 } 132 133 Binding<TestSync>* binding() { return &binding_; } 134 135 private: 136 Binding<TestSync> binding_; 137 138 DISALLOW_COPY_AND_ASSIGN(TestSyncImpl); 139 }; 140 141 class TestSyncMasterImpl : public TestSyncMaster, public TestSyncCommonImpl { 142 public: 143 explicit TestSyncMasterImpl(TestSyncMasterRequest request) 144 : binding_(this, std::move(request)) {} 145 146 // TestSyncMaster implementation: 147 void Ping(const PingCallback& callback) override { PingImpl(callback); } 148 void Echo(int32_t value, const EchoCallback& callback) override { 149 EchoImpl(value, callback); 150 } 151 void AsyncEcho(int32_t value, const AsyncEchoCallback& callback) override { 152 AsyncEchoImpl(value, callback); 153 } 154 void SendInterface(TestSyncAssociatedPtrInfo ptr) override { 155 SendInterfaceImpl(std::move(ptr)); 156 } 157 void SendRequest(TestSyncAssociatedRequest request) override { 158 SendRequestImpl(std::move(request)); 159 } 160 161 Binding<TestSyncMaster>* binding() { return &binding_; } 162 163 private: 164 Binding<TestSyncMaster> binding_; 165 166 DISALLOW_COPY_AND_ASSIGN(TestSyncMasterImpl); 167 }; 168 169 class TestSyncAssociatedImpl : public TestSync, public TestSyncCommonImpl { 170 public: 171 explicit TestSyncAssociatedImpl(TestSyncAssociatedRequest request) 172 : binding_(this, std::move(request)) {} 173 174 // TestSync implementation: 175 void Ping(const PingCallback& callback) override { PingImpl(callback); } 176 void Echo(int32_t value, const EchoCallback& callback) override { 177 EchoImpl(value, callback); 178 } 179 void AsyncEcho(int32_t value, const AsyncEchoCallback& callback) override { 180 AsyncEchoImpl(value, callback); 181 } 182 183 AssociatedBinding<TestSync>* binding() { return &binding_; } 184 185 private: 186 AssociatedBinding<TestSync> binding_; 187 188 DISALLOW_COPY_AND_ASSIGN(TestSyncAssociatedImpl); 189 }; 190 191 template <typename Interface> 192 struct ImplTraits; 193 194 template <> 195 struct ImplTraits<TestSync> { 196 using Type = TestSyncImpl; 197 }; 198 199 template <> 200 struct ImplTraits<TestSyncMaster> { 201 using Type = TestSyncMasterImpl; 202 }; 203 204 template <typename Interface> 205 class TestSyncServiceThread { 206 public: 207 TestSyncServiceThread() 208 : thread_("TestSyncServiceThread"), ping_called_(false) { 209 thread_.Start(); 210 } 211 212 void SetUp(InterfaceRequest<Interface> request) { 213 CHECK(thread_.task_runner()->BelongsToCurrentThread()); 214 impl_.reset(new typename ImplTraits<Interface>::Type(std::move(request))); 215 impl_->set_ping_handler( 216 [this](const typename Interface::PingCallback& callback) { 217 { 218 base::AutoLock locker(lock_); 219 ping_called_ = true; 220 } 221 callback.Run(); 222 }); 223 } 224 225 void TearDown() { 226 CHECK(thread_.task_runner()->BelongsToCurrentThread()); 227 impl_.reset(); 228 } 229 230 base::Thread* thread() { return &thread_; } 231 bool ping_called() const { 232 base::AutoLock locker(lock_); 233 return ping_called_; 234 } 235 236 private: 237 base::Thread thread_; 238 239 std::unique_ptr<typename ImplTraits<Interface>::Type> impl_; 240 241 mutable base::Lock lock_; 242 bool ping_called_; 243 244 DISALLOW_COPY_AND_ASSIGN(TestSyncServiceThread); 245 }; 246 247 class SyncMethodTest : public testing::Test { 248 public: 249 SyncMethodTest() {} 250 ~SyncMethodTest() override { base::RunLoop().RunUntilIdle(); } 251 252 protected: 253 base::MessageLoop loop_; 254 }; 255 256 template <typename T> 257 class SyncMethodCommonTest : public SyncMethodTest { 258 public: 259 SyncMethodCommonTest() {} 260 ~SyncMethodCommonTest() override {} 261 }; 262 263 class SyncMethodAssociatedTest : public SyncMethodTest { 264 public: 265 SyncMethodAssociatedTest() {} 266 ~SyncMethodAssociatedTest() override {} 267 268 protected: 269 void SetUp() override { 270 master_impl_.reset(new TestSyncMasterImpl(GetProxy(&master_ptr_))); 271 272 master_ptr_.associated_group()->CreateAssociatedInterface( 273 AssociatedGroup::WILL_PASS_REQUEST, &asso_ptr_info_, &asso_request_); 274 master_ptr_.associated_group()->CreateAssociatedInterface( 275 AssociatedGroup::WILL_PASS_PTR, &opposite_asso_ptr_info_, 276 &opposite_asso_request_); 277 278 master_impl_->set_send_interface_handler( 279 [this](TestSyncAssociatedPtrInfo ptr) { 280 opposite_asso_ptr_info_ = std::move(ptr); 281 }); 282 base::RunLoop run_loop; 283 master_impl_->set_send_request_handler( 284 [this, &run_loop](TestSyncAssociatedRequest request) { 285 asso_request_ = std::move(request); 286 run_loop.Quit(); 287 }); 288 289 master_ptr_->SendInterface(std::move(opposite_asso_ptr_info_)); 290 master_ptr_->SendRequest(std::move(asso_request_)); 291 run_loop.Run(); 292 } 293 294 void TearDown() override { 295 asso_ptr_info_ = TestSyncAssociatedPtrInfo(); 296 asso_request_ = TestSyncAssociatedRequest(); 297 opposite_asso_ptr_info_ = TestSyncAssociatedPtrInfo(); 298 opposite_asso_request_ = TestSyncAssociatedRequest(); 299 300 master_ptr_ = nullptr; 301 master_impl_.reset(); 302 } 303 304 InterfacePtr<TestSyncMaster> master_ptr_; 305 std::unique_ptr<TestSyncMasterImpl> master_impl_; 306 307 // An associated interface whose binding lives at the |master_impl_| side. 308 TestSyncAssociatedPtrInfo asso_ptr_info_; 309 TestSyncAssociatedRequest asso_request_; 310 311 // An associated interface whose binding lives at the |master_ptr_| side. 312 TestSyncAssociatedPtrInfo opposite_asso_ptr_info_; 313 TestSyncAssociatedRequest opposite_asso_request_; 314 }; 315 316 void SetFlagAndRunClosure(bool* flag, const base::Closure& closure) { 317 *flag = true; 318 closure.Run(); 319 } 320 321 void ExpectValueAndRunClosure(int32_t expected_value, 322 const base::Closure& closure, 323 int32_t value) { 324 EXPECT_EQ(expected_value, value); 325 closure.Run(); 326 } 327 328 template <typename Func> 329 void CallAsyncEchoCallback(Func func, int32_t value) { 330 func(value); 331 } 332 333 template <typename Func> 334 TestSync::AsyncEchoCallback BindAsyncEchoCallback(Func func) { 335 return base::Bind(&CallAsyncEchoCallback<Func>, func); 336 } 337 338 // TestSync and TestSyncMaster exercise Router and MultiplexRouter, 339 // respectively. 340 using InterfaceTypes = testing::Types<TestSync, TestSyncMaster>; 341 TYPED_TEST_CASE(SyncMethodCommonTest, InterfaceTypes); 342 343 TYPED_TEST(SyncMethodCommonTest, CallSyncMethodAsynchronously) { 344 InterfacePtr<TypeParam> ptr; 345 typename ImplTraits<TypeParam>::Type impl(GetProxy(&ptr)); 346 347 base::RunLoop run_loop; 348 ptr->Echo(123, base::Bind(&ExpectValueAndRunClosure, 123, 349 run_loop.QuitClosure())); 350 run_loop.Run(); 351 } 352 353 TYPED_TEST(SyncMethodCommonTest, BasicSyncCalls) { 354 InterfacePtr<TypeParam> ptr; 355 356 TestSyncServiceThread<TypeParam> service_thread; 357 service_thread.thread()->task_runner()->PostTask( 358 FROM_HERE, base::Bind(&TestSyncServiceThread<TypeParam>::SetUp, 359 base::Unretained(&service_thread), 360 base::Passed(GetProxy(&ptr)))); 361 ASSERT_TRUE(ptr->Ping()); 362 ASSERT_TRUE(service_thread.ping_called()); 363 364 int32_t output_value = -1; 365 ASSERT_TRUE(ptr->Echo(42, &output_value)); 366 ASSERT_EQ(42, output_value); 367 368 base::RunLoop run_loop; 369 service_thread.thread()->task_runner()->PostTaskAndReply( 370 FROM_HERE, base::Bind(&TestSyncServiceThread<TypeParam>::TearDown, 371 base::Unretained(&service_thread)), 372 run_loop.QuitClosure()); 373 run_loop.Run(); 374 } 375 376 TYPED_TEST(SyncMethodCommonTest, ReenteredBySyncMethodBinding) { 377 // Test that an interface pointer waiting for a sync call response can be 378 // reentered by a binding serving sync methods on the same thread. 379 380 InterfacePtr<TypeParam> ptr; 381 // The binding lives on the same thread as the interface pointer. 382 typename ImplTraits<TypeParam>::Type impl(GetProxy(&ptr)); 383 int32_t output_value = -1; 384 ASSERT_TRUE(ptr->Echo(42, &output_value)); 385 EXPECT_EQ(42, output_value); 386 } 387 388 TYPED_TEST(SyncMethodCommonTest, InterfacePtrDestroyedDuringSyncCall) { 389 // Test that it won't result in crash or hang if an interface pointer is 390 // destroyed while it is waiting for a sync call response. 391 392 InterfacePtr<TypeParam> ptr; 393 typename ImplTraits<TypeParam>::Type impl(GetProxy(&ptr)); 394 impl.set_ping_handler([&ptr](const TestSync::PingCallback& callback) { 395 ptr.reset(); 396 callback.Run(); 397 }); 398 ASSERT_FALSE(ptr->Ping()); 399 } 400 401 TYPED_TEST(SyncMethodCommonTest, BindingDestroyedDuringSyncCall) { 402 // Test that it won't result in crash or hang if a binding is 403 // closed (and therefore the message pipe handle is closed) while the 404 // corresponding interface pointer is waiting for a sync call response. 405 406 InterfacePtr<TypeParam> ptr; 407 typename ImplTraits<TypeParam>::Type impl(GetProxy(&ptr)); 408 impl.set_ping_handler([&impl](const TestSync::PingCallback& callback) { 409 impl.binding()->Close(); 410 callback.Run(); 411 }); 412 ASSERT_FALSE(ptr->Ping()); 413 } 414 415 TYPED_TEST(SyncMethodCommonTest, NestedSyncCallsWithInOrderResponses) { 416 // Test that we can call a sync method on an interface ptr, while there is 417 // already a sync call ongoing. The responses arrive in order. 418 419 InterfacePtr<TypeParam> ptr; 420 typename ImplTraits<TypeParam>::Type impl(GetProxy(&ptr)); 421 422 // The same variable is used to store the output of the two sync calls, in 423 // order to test that responses are handled in the correct order. 424 int32_t result_value = -1; 425 426 bool first_call = true; 427 impl.set_echo_handler([&first_call, &ptr, &result_value]( 428 int32_t value, const TestSync::EchoCallback& callback) { 429 if (first_call) { 430 first_call = false; 431 ASSERT_TRUE(ptr->Echo(456, &result_value)); 432 EXPECT_EQ(456, result_value); 433 } 434 callback.Run(value); 435 }); 436 437 ASSERT_TRUE(ptr->Echo(123, &result_value)); 438 EXPECT_EQ(123, result_value); 439 } 440 441 TYPED_TEST(SyncMethodCommonTest, NestedSyncCallsWithOutOfOrderResponses) { 442 // Test that we can call a sync method on an interface ptr, while there is 443 // already a sync call ongoing. The responses arrive out of order. 444 445 InterfacePtr<TypeParam> ptr; 446 typename ImplTraits<TypeParam>::Type impl(GetProxy(&ptr)); 447 448 // The same variable is used to store the output of the two sync calls, in 449 // order to test that responses are handled in the correct order. 450 int32_t result_value = -1; 451 452 bool first_call = true; 453 impl.set_echo_handler([&first_call, &ptr, &result_value]( 454 int32_t value, const TestSync::EchoCallback& callback) { 455 callback.Run(value); 456 if (first_call) { 457 first_call = false; 458 ASSERT_TRUE(ptr->Echo(456, &result_value)); 459 EXPECT_EQ(456, result_value); 460 } 461 }); 462 463 ASSERT_TRUE(ptr->Echo(123, &result_value)); 464 EXPECT_EQ(123, result_value); 465 } 466 467 TYPED_TEST(SyncMethodCommonTest, AsyncResponseQueuedDuringSyncCall) { 468 // Test that while an interface pointer is waiting for the response to a sync 469 // call, async responses are queued until the sync call completes. 470 471 InterfacePtr<TypeParam> ptr; 472 typename ImplTraits<TypeParam>::Type impl(GetProxy(&ptr)); 473 474 int32_t async_echo_request_value = -1; 475 TestSync::AsyncEchoCallback async_echo_request_callback; 476 base::RunLoop run_loop1; 477 impl.set_async_echo_handler( 478 [&async_echo_request_value, &async_echo_request_callback, &run_loop1]( 479 int32_t value, const TestSync::AsyncEchoCallback& callback) { 480 async_echo_request_value = value; 481 async_echo_request_callback = callback; 482 run_loop1.Quit(); 483 }); 484 485 bool async_echo_response_dispatched = false; 486 base::RunLoop run_loop2; 487 ptr->AsyncEcho( 488 123, 489 BindAsyncEchoCallback( 490 [&async_echo_response_dispatched, &run_loop2](int32_t result) { 491 async_echo_response_dispatched = true; 492 EXPECT_EQ(123, result); 493 run_loop2.Quit(); 494 })); 495 // Run until the AsyncEcho request reaches the service side. 496 run_loop1.Run(); 497 498 impl.set_echo_handler( 499 [&async_echo_request_value, &async_echo_request_callback]( 500 int32_t value, const TestSync::EchoCallback& callback) { 501 // Send back the async response first. 502 EXPECT_FALSE(async_echo_request_callback.is_null()); 503 async_echo_request_callback.Run(async_echo_request_value); 504 505 callback.Run(value); 506 }); 507 508 int32_t result_value = -1; 509 ASSERT_TRUE(ptr->Echo(456, &result_value)); 510 EXPECT_EQ(456, result_value); 511 512 // Although the AsyncEcho response arrives before the Echo response, it should 513 // be queued and not yet dispatched. 514 EXPECT_FALSE(async_echo_response_dispatched); 515 516 // Run until the AsyncEcho response is dispatched. 517 run_loop2.Run(); 518 519 EXPECT_TRUE(async_echo_response_dispatched); 520 } 521 522 TYPED_TEST(SyncMethodCommonTest, AsyncRequestQueuedDuringSyncCall) { 523 // Test that while an interface pointer is waiting for the response to a sync 524 // call, async requests for a binding running on the same thread are queued 525 // until the sync call completes. 526 527 InterfacePtr<TypeParam> ptr; 528 typename ImplTraits<TypeParam>::Type impl(GetProxy(&ptr)); 529 530 bool async_echo_request_dispatched = false; 531 impl.set_async_echo_handler([&async_echo_request_dispatched]( 532 int32_t value, const TestSync::AsyncEchoCallback& callback) { 533 async_echo_request_dispatched = true; 534 callback.Run(value); 535 }); 536 537 bool async_echo_response_dispatched = false; 538 base::RunLoop run_loop; 539 ptr->AsyncEcho( 540 123, 541 BindAsyncEchoCallback( 542 [&async_echo_response_dispatched, &run_loop](int32_t result) { 543 async_echo_response_dispatched = true; 544 EXPECT_EQ(123, result); 545 run_loop.Quit(); 546 })); 547 548 impl.set_echo_handler([&async_echo_request_dispatched]( 549 int32_t value, const TestSync::EchoCallback& callback) { 550 // Although the AsyncEcho request is sent before the Echo request, it 551 // shouldn't be dispatched yet at this point, because there is an ongoing 552 // sync call on the same thread. 553 EXPECT_FALSE(async_echo_request_dispatched); 554 callback.Run(value); 555 }); 556 557 int32_t result_value = -1; 558 ASSERT_TRUE(ptr->Echo(456, &result_value)); 559 EXPECT_EQ(456, result_value); 560 561 // Although the AsyncEcho request is sent before the Echo request, it 562 // shouldn't be dispatched yet. 563 EXPECT_FALSE(async_echo_request_dispatched); 564 565 // Run until the AsyncEcho response is dispatched. 566 run_loop.Run(); 567 568 EXPECT_TRUE(async_echo_response_dispatched); 569 } 570 571 TYPED_TEST(SyncMethodCommonTest, 572 QueuedMessagesProcessedBeforeErrorNotification) { 573 // Test that while an interface pointer is waiting for the response to a sync 574 // call, async responses are queued. If the message pipe is disconnected 575 // before the queued messages are processed, the connection error 576 // notification is delayed until all the queued messages are processed. 577 578 InterfacePtr<TypeParam> ptr; 579 typename ImplTraits<TypeParam>::Type impl(GetProxy(&ptr)); 580 581 int32_t async_echo_request_value = -1; 582 TestSync::AsyncEchoCallback async_echo_request_callback; 583 base::RunLoop run_loop1; 584 impl.set_async_echo_handler( 585 [&async_echo_request_value, &async_echo_request_callback, &run_loop1]( 586 int32_t value, const TestSync::AsyncEchoCallback& callback) { 587 async_echo_request_value = value; 588 async_echo_request_callback = callback; 589 run_loop1.Quit(); 590 }); 591 592 bool async_echo_response_dispatched = false; 593 bool connection_error_dispatched = false; 594 base::RunLoop run_loop2; 595 ptr->AsyncEcho( 596 123, 597 BindAsyncEchoCallback( 598 [&async_echo_response_dispatched, &connection_error_dispatched, &ptr, 599 &run_loop2](int32_t result) { 600 async_echo_response_dispatched = true; 601 // At this point, error notification should not be dispatched 602 // yet. 603 EXPECT_FALSE(connection_error_dispatched); 604 EXPECT_FALSE(ptr.encountered_error()); 605 EXPECT_EQ(123, result); 606 run_loop2.Quit(); 607 })); 608 // Run until the AsyncEcho request reaches the service side. 609 run_loop1.Run(); 610 611 impl.set_echo_handler( 612 [&impl, &async_echo_request_value, &async_echo_request_callback]( 613 int32_t value, const TestSync::EchoCallback& callback) { 614 // Send back the async response first. 615 EXPECT_FALSE(async_echo_request_callback.is_null()); 616 async_echo_request_callback.Run(async_echo_request_value); 617 618 impl.binding()->Close(); 619 }); 620 621 base::RunLoop run_loop3; 622 ptr.set_connection_error_handler( 623 base::Bind(&SetFlagAndRunClosure, &connection_error_dispatched, 624 run_loop3.QuitClosure())); 625 626 int32_t result_value = -1; 627 ASSERT_FALSE(ptr->Echo(456, &result_value)); 628 EXPECT_EQ(-1, result_value); 629 ASSERT_FALSE(connection_error_dispatched); 630 EXPECT_FALSE(ptr.encountered_error()); 631 632 // Although the AsyncEcho response arrives before the Echo response, it should 633 // be queued and not yet dispatched. 634 EXPECT_FALSE(async_echo_response_dispatched); 635 636 // Run until the AsyncEcho response is dispatched. 637 run_loop2.Run(); 638 639 EXPECT_TRUE(async_echo_response_dispatched); 640 641 // Run until the error notification is dispatched. 642 run_loop3.Run(); 643 644 ASSERT_TRUE(connection_error_dispatched); 645 EXPECT_TRUE(ptr.encountered_error()); 646 } 647 648 TYPED_TEST(SyncMethodCommonTest, InvalidMessageDuringSyncCall) { 649 // Test that while an interface pointer is waiting for the response to a sync 650 // call, an invalid incoming message will disconnect the message pipe, cause 651 // the sync call to return false, and run the connection error handler 652 // asynchronously. 653 654 MessagePipe pipe; 655 656 InterfacePtr<TypeParam> ptr; 657 ptr.Bind(InterfacePtrInfo<TypeParam>(std::move(pipe.handle0), 0u)); 658 659 MessagePipeHandle raw_binding_handle = pipe.handle1.get(); 660 typename ImplTraits<TypeParam>::Type impl( 661 MakeRequest<TypeParam>(std::move(pipe.handle1))); 662 663 impl.set_echo_handler([&raw_binding_handle]( 664 int32_t value, const TestSync::EchoCallback& callback) { 665 // Write a 1-byte message, which is considered invalid. 666 char invalid_message = 0; 667 MojoResult result = 668 WriteMessageRaw(raw_binding_handle, &invalid_message, 1u, nullptr, 0u, 669 MOJO_WRITE_MESSAGE_FLAG_NONE); 670 ASSERT_EQ(MOJO_RESULT_OK, result); 671 callback.Run(value); 672 }); 673 674 bool connection_error_dispatched = false; 675 base::RunLoop run_loop; 676 ptr.set_connection_error_handler( 677 base::Bind(&SetFlagAndRunClosure, &connection_error_dispatched, 678 run_loop.QuitClosure())); 679 680 int32_t result_value = -1; 681 ASSERT_FALSE(ptr->Echo(456, &result_value)); 682 EXPECT_EQ(-1, result_value); 683 ASSERT_FALSE(connection_error_dispatched); 684 685 run_loop.Run(); 686 ASSERT_TRUE(connection_error_dispatched); 687 } 688 689 TEST_F(SyncMethodAssociatedTest, ReenteredBySyncMethodAssoBindingOfSameRouter) { 690 // Test that an interface pointer waiting for a sync call response can be 691 // reentered by an associated binding serving sync methods on the same thread. 692 // The associated binding belongs to the same MultiplexRouter as the waiting 693 // interface pointer. 694 695 TestSyncAssociatedImpl opposite_asso_impl(std::move(opposite_asso_request_)); 696 TestSyncAssociatedPtr opposite_asso_ptr; 697 opposite_asso_ptr.Bind(std::move(opposite_asso_ptr_info_)); 698 699 master_impl_->set_echo_handler([&opposite_asso_ptr]( 700 int32_t value, const TestSyncMaster::EchoCallback& callback) { 701 int32_t result_value = -1; 702 703 ASSERT_TRUE(opposite_asso_ptr->Echo(123, &result_value)); 704 EXPECT_EQ(123, result_value); 705 callback.Run(value); 706 }); 707 708 int32_t result_value = -1; 709 ASSERT_TRUE(master_ptr_->Echo(456, &result_value)); 710 EXPECT_EQ(456, result_value); 711 } 712 713 TEST_F(SyncMethodAssociatedTest, 714 ReenteredBySyncMethodAssoBindingOfDifferentRouter) { 715 // Test that an interface pointer waiting for a sync call response can be 716 // reentered by an associated binding serving sync methods on the same thread. 717 // The associated binding belongs to a different MultiplexRouter as the 718 // waiting interface pointer. 719 720 TestSyncAssociatedImpl asso_impl(std::move(asso_request_)); 721 TestSyncAssociatedPtr asso_ptr; 722 asso_ptr.Bind(std::move(asso_ptr_info_)); 723 724 master_impl_->set_echo_handler( 725 [&asso_ptr](int32_t value, const TestSyncMaster::EchoCallback& callback) { 726 int32_t result_value = -1; 727 728 ASSERT_TRUE(asso_ptr->Echo(123, &result_value)); 729 EXPECT_EQ(123, result_value); 730 callback.Run(value); 731 }); 732 733 int32_t result_value = -1; 734 ASSERT_TRUE(master_ptr_->Echo(456, &result_value)); 735 EXPECT_EQ(456, result_value); 736 } 737 738 // TODO(yzshen): Add more tests related to associated interfaces. 739 740 } // namespace 741 } // namespace test 742 } // namespace mojo 743