Home | History | Annotate | Download | only in tests
      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