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/run_loop.h"
11 #include "base/sequence_token.h"
12 #include "base/task_scheduler/post_task.h"
13 #include "base/test/scoped_task_environment.h"
14 #include "base/threading/thread.h"
15 #include "mojo/public/cpp/bindings/associated_binding.h"
16 #include "mojo/public/cpp/bindings/binding.h"
17 #include "mojo/public/cpp/bindings/tests/bindings_test_base.h"
18 #include "mojo/public/interfaces/bindings/tests/test_sync_methods.mojom.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 
21 namespace mojo {
22 namespace test {
23 namespace {
24 
25 template <typename... Args>
26 struct LambdaBinder {
27   using CallbackType = base::Callback<void(Args...)>;
28 
29   template <typename Func>
RunLambdamojo::test::__anone24243e80111::LambdaBinder30   static void RunLambda(Func func, Args... args) {
31     func(std::move(args)...);
32   }
33 
34   template <typename Func>
BindLambdamojo::test::__anone24243e80111::LambdaBinder35   static CallbackType BindLambda(Func func) {
36     return base::Bind(&LambdaBinder::RunLambda<Func>, func);
37   }
38 };
39 
40 class TestSyncCommonImpl {
41  public:
TestSyncCommonImpl()42   TestSyncCommonImpl() {}
43 
44   using PingHandler = base::Callback<void(const base::Callback<void()>&)>;
45   using PingBinder = LambdaBinder<const base::Callback<void()>&>;
46   template <typename Func>
set_ping_handler(Func handler)47   void set_ping_handler(Func handler) {
48     ping_handler_ = PingBinder::BindLambda(handler);
49   }
50 
51   using EchoHandler =
52       base::Callback<void(int32_t, const base::Callback<void(int32_t)>&)>;
53   using EchoBinder =
54       LambdaBinder<int32_t, const base::Callback<void(int32_t)>&>;
55   template <typename Func>
set_echo_handler(Func handler)56   void set_echo_handler(Func handler) {
57     echo_handler_ = EchoBinder::BindLambda(handler);
58   }
59 
60   using AsyncEchoHandler =
61       base::Callback<void(int32_t, const base::Callback<void(int32_t)>&)>;
62   using AsyncEchoBinder =
63       LambdaBinder<int32_t, const base::Callback<void(int32_t)>&>;
64   template <typename Func>
set_async_echo_handler(Func handler)65   void set_async_echo_handler(Func handler) {
66     async_echo_handler_ = AsyncEchoBinder::BindLambda(handler);
67   }
68 
69   using SendInterfaceHandler = base::Callback<void(TestSyncAssociatedPtrInfo)>;
70   using SendInterfaceBinder = LambdaBinder<TestSyncAssociatedPtrInfo>;
71   template <typename Func>
set_send_interface_handler(Func handler)72   void set_send_interface_handler(Func handler) {
73     send_interface_handler_ = SendInterfaceBinder::BindLambda(handler);
74   }
75 
76   using SendRequestHandler = base::Callback<void(TestSyncAssociatedRequest)>;
77   using SendRequestBinder = LambdaBinder<TestSyncAssociatedRequest>;
78   template <typename Func>
set_send_request_handler(Func handler)79   void set_send_request_handler(Func handler) {
80     send_request_handler_ = SendRequestBinder::BindLambda(handler);
81   }
82 
PingImpl(const base::Callback<void ()> & callback)83   void PingImpl(const base::Callback<void()>& callback) {
84     if (ping_handler_.is_null()) {
85       callback.Run();
86       return;
87     }
88     ping_handler_.Run(callback);
89   }
EchoImpl(int32_t value,const base::Callback<void (int32_t)> & callback)90   void EchoImpl(int32_t value, const base::Callback<void(int32_t)>& callback) {
91     if (echo_handler_.is_null()) {
92       callback.Run(value);
93       return;
94     }
95     echo_handler_.Run(value, callback);
96   }
AsyncEchoImpl(int32_t value,const base::Callback<void (int32_t)> & callback)97   void AsyncEchoImpl(int32_t value,
98                      const base::Callback<void(int32_t)>& callback) {
99     if (async_echo_handler_.is_null()) {
100       callback.Run(value);
101       return;
102     }
103     async_echo_handler_.Run(value, callback);
104   }
SendInterfaceImpl(TestSyncAssociatedPtrInfo ptr)105   void SendInterfaceImpl(TestSyncAssociatedPtrInfo ptr) {
106     send_interface_handler_.Run(std::move(ptr));
107   }
SendRequestImpl(TestSyncAssociatedRequest request)108   void SendRequestImpl(TestSyncAssociatedRequest request) {
109     send_request_handler_.Run(std::move(request));
110   }
111 
112  private:
113   PingHandler ping_handler_;
114   EchoHandler echo_handler_;
115   AsyncEchoHandler async_echo_handler_;
116   SendInterfaceHandler send_interface_handler_;
117   SendRequestHandler send_request_handler_;
118 
119   DISALLOW_COPY_AND_ASSIGN(TestSyncCommonImpl);
120 };
121 
122 class TestSyncImpl : public TestSync, public TestSyncCommonImpl {
123  public:
TestSyncImpl(TestSyncRequest request)124   explicit TestSyncImpl(TestSyncRequest request)
125       : binding_(this, std::move(request)) {}
126 
127   // TestSync implementation:
Ping(const PingCallback & callback)128   void Ping(const PingCallback& callback) override { PingImpl(callback); }
Echo(int32_t value,const EchoCallback & callback)129   void Echo(int32_t value, const EchoCallback& callback) override {
130     EchoImpl(value, callback);
131   }
AsyncEcho(int32_t value,const AsyncEchoCallback & callback)132   void AsyncEcho(int32_t value, const AsyncEchoCallback& callback) override {
133     AsyncEchoImpl(value, callback);
134   }
135 
binding()136   Binding<TestSync>* binding() { return &binding_; }
137 
138  private:
139   Binding<TestSync> binding_;
140 
141   DISALLOW_COPY_AND_ASSIGN(TestSyncImpl);
142 };
143 
144 class TestSyncMasterImpl : public TestSyncMaster, public TestSyncCommonImpl {
145  public:
TestSyncMasterImpl(TestSyncMasterRequest request)146   explicit TestSyncMasterImpl(TestSyncMasterRequest request)
147       : binding_(this, std::move(request)) {}
148 
149   // TestSyncMaster implementation:
Ping(const PingCallback & callback)150   void Ping(const PingCallback& callback) override { PingImpl(callback); }
Echo(int32_t value,const EchoCallback & callback)151   void Echo(int32_t value, const EchoCallback& callback) override {
152     EchoImpl(value, callback);
153   }
AsyncEcho(int32_t value,const AsyncEchoCallback & callback)154   void AsyncEcho(int32_t value, const AsyncEchoCallback& callback) override {
155     AsyncEchoImpl(value, callback);
156   }
SendInterface(TestSyncAssociatedPtrInfo ptr)157   void SendInterface(TestSyncAssociatedPtrInfo ptr) override {
158     SendInterfaceImpl(std::move(ptr));
159   }
SendRequest(TestSyncAssociatedRequest request)160   void SendRequest(TestSyncAssociatedRequest request) override {
161     SendRequestImpl(std::move(request));
162   }
163 
binding()164   Binding<TestSyncMaster>* binding() { return &binding_; }
165 
166  private:
167   Binding<TestSyncMaster> binding_;
168 
169   DISALLOW_COPY_AND_ASSIGN(TestSyncMasterImpl);
170 };
171 
172 class TestSyncAssociatedImpl : public TestSync, public TestSyncCommonImpl {
173  public:
TestSyncAssociatedImpl(TestSyncAssociatedRequest request)174   explicit TestSyncAssociatedImpl(TestSyncAssociatedRequest request)
175       : binding_(this, std::move(request)) {}
176 
177   // TestSync implementation:
Ping(const PingCallback & callback)178   void Ping(const PingCallback& callback) override { PingImpl(callback); }
Echo(int32_t value,const EchoCallback & callback)179   void Echo(int32_t value, const EchoCallback& callback) override {
180     EchoImpl(value, callback);
181   }
AsyncEcho(int32_t value,const AsyncEchoCallback & callback)182   void AsyncEcho(int32_t value, const AsyncEchoCallback& callback) override {
183     AsyncEchoImpl(value, callback);
184   }
185 
binding()186   AssociatedBinding<TestSync>* binding() { return &binding_; }
187 
188  private:
189   AssociatedBinding<TestSync> binding_;
190 
191   DISALLOW_COPY_AND_ASSIGN(TestSyncAssociatedImpl);
192 };
193 
194 template <typename Interface>
195 struct ImplTraits;
196 
197 template <>
198 struct ImplTraits<TestSync> {
199   using Type = TestSyncImpl;
200 };
201 
202 template <>
203 struct ImplTraits<TestSyncMaster> {
204   using Type = TestSyncMasterImpl;
205 };
206 
207 template <typename Interface>
208 using ImplTypeFor = typename ImplTraits<Interface>::Type;
209 
210 // A wrapper for either an InterfacePtr or scoped_refptr<ThreadSafeInterfacePtr>
211 // that exposes the InterfacePtr interface.
212 template <typename Interface>
213 class PtrWrapper {
214  public:
PtrWrapper(InterfacePtr<Interface> ptr)215   explicit PtrWrapper(InterfacePtr<Interface> ptr) : ptr_(std::move(ptr)) {}
216 
PtrWrapper(scoped_refptr<ThreadSafeInterfacePtr<Interface>> thread_safe_ptr)217   explicit PtrWrapper(
218       scoped_refptr<ThreadSafeInterfacePtr<Interface>> thread_safe_ptr)
219       : thread_safe_ptr_(thread_safe_ptr) {}
220 
221   PtrWrapper(PtrWrapper&& other) = default;
222 
operator ->()223   Interface* operator->() {
224     return thread_safe_ptr_ ? thread_safe_ptr_->get() : ptr_.get();
225   }
226 
set_connection_error_handler(const base::Closure & error_handler)227   void set_connection_error_handler(const base::Closure& error_handler) {
228     DCHECK(!thread_safe_ptr_);
229     ptr_.set_connection_error_handler(error_handler);
230   }
231 
reset()232   void reset() {
233     ptr_ = nullptr;
234     thread_safe_ptr_ = nullptr;
235   }
236 
237  private:
238   InterfacePtr<Interface> ptr_;
239   scoped_refptr<ThreadSafeInterfacePtr<Interface>> thread_safe_ptr_;
240 
241   DISALLOW_COPY_AND_ASSIGN(PtrWrapper);
242 };
243 
244 // The type parameter for SyncMethodCommonTests and
245 // SyncMethodOnSequenceCommonTests for varying the Interface and whether to use
246 // InterfacePtr or ThreadSafeInterfacePtr.
247 template <typename InterfaceT,
248           bool use_thread_safe_ptr,
249           BindingsTestSerializationMode serialization_mode>
250 struct TestParams {
251   using Interface = InterfaceT;
252   static const bool kIsThreadSafeInterfacePtrTest = use_thread_safe_ptr;
253 
Wrapmojo::test::__anone24243e80111::TestParams254   static PtrWrapper<InterfaceT> Wrap(InterfacePtr<Interface> ptr) {
255     if (kIsThreadSafeInterfacePtrTest) {
256       return PtrWrapper<Interface>(
257           ThreadSafeInterfacePtr<Interface>::Create(std::move(ptr)));
258     } else {
259       return PtrWrapper<Interface>(std::move(ptr));
260     }
261   }
262 
263   static const BindingsTestSerializationMode kSerializationMode =
264       serialization_mode;
265 };
266 
267 template <typename Interface>
268 class TestSyncServiceSequence {
269  public:
TestSyncServiceSequence()270   TestSyncServiceSequence()
271       : task_runner_(base::CreateSequencedTaskRunnerWithTraits({})),
272         ping_called_(false) {}
273 
SetUp(InterfaceRequest<Interface> request)274   void SetUp(InterfaceRequest<Interface> request) {
275     CHECK(task_runner()->RunsTasksInCurrentSequence());
276     impl_.reset(new ImplTypeFor<Interface>(std::move(request)));
277     impl_->set_ping_handler(
278         [this](const typename Interface::PingCallback& callback) {
279           {
280             base::AutoLock locker(lock_);
281             ping_called_ = true;
282           }
283           callback.Run();
284         });
285   }
286 
TearDown()287   void TearDown() {
288     CHECK(task_runner()->RunsTasksInCurrentSequence());
289     impl_.reset();
290   }
291 
task_runner()292   base::SequencedTaskRunner* task_runner() { return task_runner_.get(); }
ping_called() const293   bool ping_called() const {
294     base::AutoLock locker(lock_);
295     return ping_called_;
296   }
297 
298  private:
299   scoped_refptr<base::SequencedTaskRunner> task_runner_;
300 
301   std::unique_ptr<ImplTypeFor<Interface>> impl_;
302 
303   mutable base::Lock lock_;
304   bool ping_called_;
305 
306   DISALLOW_COPY_AND_ASSIGN(TestSyncServiceSequence);
307 };
308 
309 class SyncMethodTest : public testing::Test {
310  public:
SyncMethodTest()311   SyncMethodTest() {}
~SyncMethodTest()312   ~SyncMethodTest() override { base::RunLoop().RunUntilIdle(); }
313 
314  protected:
315   base::test::ScopedTaskEnvironment task_environment;
316 };
317 
318 template <typename TypeParam>
319 class SyncMethodCommonTest : public SyncMethodTest {
320  public:
SyncMethodCommonTest()321   SyncMethodCommonTest() {}
~SyncMethodCommonTest()322   ~SyncMethodCommonTest() override {}
323 
SetUp()324   void SetUp() override {
325     BindingsTestBase::SetupSerializationBehavior(TypeParam::kSerializationMode);
326   }
327 };
328 
329 class SyncMethodAssociatedTest : public SyncMethodTest {
330  public:
SyncMethodAssociatedTest()331   SyncMethodAssociatedTest() {}
~SyncMethodAssociatedTest()332   ~SyncMethodAssociatedTest() override {}
333 
334  protected:
SetUp()335   void SetUp() override {
336     master_impl_.reset(new TestSyncMasterImpl(MakeRequest(&master_ptr_)));
337 
338     asso_request_ = MakeRequest(&asso_ptr_info_);
339     opposite_asso_request_ = MakeRequest(&opposite_asso_ptr_info_);
340 
341     master_impl_->set_send_interface_handler(
342         [this](TestSyncAssociatedPtrInfo ptr) {
343           opposite_asso_ptr_info_ = std::move(ptr);
344         });
345     base::RunLoop run_loop;
346     master_impl_->set_send_request_handler(
347         [this, &run_loop](TestSyncAssociatedRequest request) {
348           asso_request_ = std::move(request);
349           run_loop.Quit();
350         });
351 
352     master_ptr_->SendInterface(std::move(opposite_asso_ptr_info_));
353     master_ptr_->SendRequest(std::move(asso_request_));
354     run_loop.Run();
355   }
356 
TearDown()357   void TearDown() override {
358     asso_ptr_info_ = TestSyncAssociatedPtrInfo();
359     asso_request_ = TestSyncAssociatedRequest();
360     opposite_asso_ptr_info_ = TestSyncAssociatedPtrInfo();
361     opposite_asso_request_ = TestSyncAssociatedRequest();
362 
363     master_ptr_ = nullptr;
364     master_impl_.reset();
365   }
366 
367   InterfacePtr<TestSyncMaster> master_ptr_;
368   std::unique_ptr<TestSyncMasterImpl> master_impl_;
369 
370   // An associated interface whose binding lives at the |master_impl_| side.
371   TestSyncAssociatedPtrInfo asso_ptr_info_;
372   TestSyncAssociatedRequest asso_request_;
373 
374   // An associated interface whose binding lives at the |master_ptr_| side.
375   TestSyncAssociatedPtrInfo opposite_asso_ptr_info_;
376   TestSyncAssociatedRequest opposite_asso_request_;
377 };
378 
SetFlagAndRunClosure(bool * flag,const base::Closure & closure)379 void SetFlagAndRunClosure(bool* flag, const base::Closure& closure) {
380   *flag = true;
381   closure.Run();
382 }
383 
ExpectValueAndRunClosure(int32_t expected_value,const base::Closure & closure,int32_t value)384 void ExpectValueAndRunClosure(int32_t expected_value,
385                               const base::Closure& closure,
386                               int32_t value) {
387   EXPECT_EQ(expected_value, value);
388   closure.Run();
389 }
390 
391 template <typename Func>
CallAsyncEchoCallback(Func func,int32_t value)392 void CallAsyncEchoCallback(Func func, int32_t value) {
393   func(value);
394 }
395 
396 template <typename Func>
BindAsyncEchoCallback(Func func)397 TestSync::AsyncEchoCallback BindAsyncEchoCallback(Func func) {
398   return base::Bind(&CallAsyncEchoCallback<Func>, func);
399 }
400 
401 class SequencedTaskRunnerTestBase;
402 
403 void RunTestOnSequencedTaskRunner(
404     std::unique_ptr<SequencedTaskRunnerTestBase> test);
405 
406 class SequencedTaskRunnerTestBase {
407  public:
408   virtual ~SequencedTaskRunnerTestBase() = default;
409 
RunTest()410   void RunTest() {
411     SetUp();
412     Run();
413   }
414 
415   virtual void Run() = 0;
416 
SetUp()417   virtual void SetUp() {}
TearDown()418   virtual void TearDown() {}
419 
420  protected:
Done()421   void Done() {
422     TearDown();
423     task_runner_->PostTask(FROM_HERE, quit_closure_);
424     delete this;
425   }
426 
DoneClosure()427   base::Closure DoneClosure() {
428     return base::Bind(&SequencedTaskRunnerTestBase::Done,
429                       base::Unretained(this));
430   }
431 
432  private:
433   friend void RunTestOnSequencedTaskRunner(
434       std::unique_ptr<SequencedTaskRunnerTestBase> test);
435 
Init(const base::Closure & quit_closure)436   void Init(const base::Closure& quit_closure) {
437     task_runner_ = base::SequencedTaskRunnerHandle::Get();
438     quit_closure_ = quit_closure;
439   }
440 
441   scoped_refptr<base::SequencedTaskRunner> task_runner_;
442   base::Closure quit_closure_;
443 };
444 
445 // A helper class to launch tests on a SequencedTaskRunner. This is necessary
446 // so gtest can instantiate copies for each |TypeParam|.
447 template <typename TypeParam>
448 class SequencedTaskRunnerTestLauncher : public testing::Test {
449   base::test::ScopedTaskEnvironment task_environment;
450 };
451 
452 // Similar to SyncMethodCommonTest, but the test body runs on a
453 // SequencedTaskRunner.
454 template <typename TypeParam>
455 class SyncMethodOnSequenceCommonTest : public SequencedTaskRunnerTestBase {
456  public:
SetUp()457   void SetUp() override {
458     BindingsTestBase::SetupSerializationBehavior(TypeParam::kSerializationMode);
459     impl_ = std::make_unique<ImplTypeFor<typename TypeParam::Interface>>(
460         MakeRequest(&ptr_));
461   }
462 
463  protected:
464   InterfacePtr<typename TypeParam::Interface> ptr_;
465   std::unique_ptr<ImplTypeFor<typename TypeParam::Interface>> impl_;
466 };
467 
RunTestOnSequencedTaskRunner(std::unique_ptr<SequencedTaskRunnerTestBase> test)468 void RunTestOnSequencedTaskRunner(
469     std::unique_ptr<SequencedTaskRunnerTestBase> test) {
470   base::RunLoop run_loop;
471   test->Init(run_loop.QuitClosure());
472   base::CreateSequencedTaskRunnerWithTraits({base::WithBaseSyncPrimitives()})
473       ->PostTask(FROM_HERE, base::Bind(&SequencedTaskRunnerTestBase::RunTest,
474                                        base::Unretained(test.release())));
475   run_loop.Run();
476 }
477 
478 // TestSync (without associated interfaces) and TestSyncMaster (with associated
479 // interfaces) exercise MultiplexRouter with different configurations.
480 // Each test is run once with an InterfacePtr and once with a
481 // ThreadSafeInterfacePtr to ensure that they behave the same with respect to
482 // sync calls. Finally, all such combinations are tested in different message
483 // serialization modes.
484 using InterfaceTypes = testing::Types<
485     TestParams<TestSync,
486                true,
487                BindingsTestSerializationMode::kSerializeBeforeSend>,
488     TestParams<TestSync,
489                false,
490                BindingsTestSerializationMode::kSerializeBeforeSend>,
491     TestParams<TestSyncMaster,
492                true,
493                BindingsTestSerializationMode::kSerializeBeforeSend>,
494     TestParams<TestSyncMaster,
495                false,
496                BindingsTestSerializationMode::kSerializeBeforeSend>,
497     TestParams<TestSync,
498                true,
499                BindingsTestSerializationMode::kSerializeBeforeDispatch>,
500     TestParams<TestSync,
501                false,
502                BindingsTestSerializationMode::kSerializeBeforeDispatch>,
503     TestParams<TestSyncMaster,
504                true,
505                BindingsTestSerializationMode::kSerializeBeforeDispatch>,
506     TestParams<TestSyncMaster,
507                false,
508                BindingsTestSerializationMode::kSerializeBeforeDispatch>,
509     TestParams<TestSync, true, BindingsTestSerializationMode::kNeverSerialize>,
510     TestParams<TestSync, false, BindingsTestSerializationMode::kNeverSerialize>,
511     TestParams<TestSyncMaster,
512                true,
513                BindingsTestSerializationMode::kNeverSerialize>,
514     TestParams<TestSyncMaster,
515                false,
516                BindingsTestSerializationMode::kNeverSerialize>>;
517 
518 TYPED_TEST_CASE(SyncMethodCommonTest, InterfaceTypes);
519 TYPED_TEST_CASE(SequencedTaskRunnerTestLauncher, InterfaceTypes);
520 
TYPED_TEST(SyncMethodCommonTest,CallSyncMethodAsynchronously)521 TYPED_TEST(SyncMethodCommonTest, CallSyncMethodAsynchronously) {
522   using Interface = typename TypeParam::Interface;
523   InterfacePtr<Interface> interface_ptr;
524   ImplTypeFor<Interface> impl(MakeRequest(&interface_ptr));
525   auto ptr = TypeParam::Wrap(std::move(interface_ptr));
526 
527   base::RunLoop run_loop;
528   ptr->Echo(123, base::Bind(&ExpectValueAndRunClosure, 123,
529                             run_loop.QuitClosure()));
530   run_loop.Run();
531 }
532 
533 #define SEQUENCED_TASK_RUNNER_TYPED_TEST_NAME(fixture_name, name) \
534   fixture_name##name##_SequencedTaskRunnerTestSuffix
535 
536 #define SEQUENCED_TASK_RUNNER_TYPED_TEST(fixture_name, name)        \
537   template <typename TypeParam>                                     \
538   class SEQUENCED_TASK_RUNNER_TYPED_TEST_NAME(fixture_name, name)   \
539       : public fixture_name<TypeParam> {                            \
540     void Run() override;                                            \
541   };                                                                \
542   TYPED_TEST(SequencedTaskRunnerTestLauncher, name) {               \
543     RunTestOnSequencedTaskRunner(                                   \
544         std::make_unique<SEQUENCED_TASK_RUNNER_TYPED_TEST_NAME(     \
545                              fixture_name, name) < TypeParam>> ()); \
546   }                                                                 \
547   template <typename TypeParam>                                     \
548   void SEQUENCED_TASK_RUNNER_TYPED_TEST_NAME(fixture_name,          \
549                                              name)<TypeParam>::Run()
550 
551 #define SEQUENCED_TASK_RUNNER_TYPED_TEST_F(fixture_name, name)      \
552   template <typename TypeParam>                                     \
553   class SEQUENCED_TASK_RUNNER_TYPED_TEST_NAME(fixture_name, name);  \
554   TYPED_TEST(SequencedTaskRunnerTestLauncher, name) {               \
555     RunTestOnSequencedTaskRunner(                                   \
556         std::make_unique<SEQUENCED_TASK_RUNNER_TYPED_TEST_NAME(     \
557                              fixture_name, name) < TypeParam>> ()); \
558   }                                                                 \
559   template <typename TypeParam>                                     \
560   class SEQUENCED_TASK_RUNNER_TYPED_TEST_NAME(fixture_name, name)   \
561       : public fixture_name<TypeParam>
562 
SEQUENCED_TASK_RUNNER_TYPED_TEST(SyncMethodOnSequenceCommonTest,CallSyncMethodAsynchronously)563 SEQUENCED_TASK_RUNNER_TYPED_TEST(SyncMethodOnSequenceCommonTest,
564                                  CallSyncMethodAsynchronously) {
565   this->ptr_->Echo(
566       123, base::Bind(&ExpectValueAndRunClosure, 123, this->DoneClosure()));
567 }
568 
TYPED_TEST(SyncMethodCommonTest,BasicSyncCalls)569 TYPED_TEST(SyncMethodCommonTest, BasicSyncCalls) {
570   using Interface = typename TypeParam::Interface;
571   InterfacePtr<Interface> interface_ptr;
572   InterfaceRequest<Interface> request = MakeRequest(&interface_ptr);
573   auto ptr = TypeParam::Wrap(std::move(interface_ptr));
574 
575   TestSyncServiceSequence<Interface> service_sequence;
576   service_sequence.task_runner()->PostTask(
577       FROM_HERE,
578       base::Bind(&TestSyncServiceSequence<Interface>::SetUp,
579                  base::Unretained(&service_sequence), base::Passed(&request)));
580   ASSERT_TRUE(ptr->Ping());
581   ASSERT_TRUE(service_sequence.ping_called());
582 
583   int32_t output_value = -1;
584   ASSERT_TRUE(ptr->Echo(42, &output_value));
585   ASSERT_EQ(42, output_value);
586 
587   base::RunLoop run_loop;
588   service_sequence.task_runner()->PostTaskAndReply(
589       FROM_HERE,
590       base::Bind(&TestSyncServiceSequence<Interface>::TearDown,
591                  base::Unretained(&service_sequence)),
592       run_loop.QuitClosure());
593   run_loop.Run();
594 }
595 
TYPED_TEST(SyncMethodCommonTest,ReenteredBySyncMethodBinding)596 TYPED_TEST(SyncMethodCommonTest, ReenteredBySyncMethodBinding) {
597   // Test that an interface pointer waiting for a sync call response can be
598   // reentered by a binding serving sync methods on the same thread.
599 
600   using Interface = typename TypeParam::Interface;
601   InterfacePtr<Interface> interface_ptr;
602   // The binding lives on the same thread as the interface pointer.
603   ImplTypeFor<Interface> impl(MakeRequest(&interface_ptr));
604   auto ptr = TypeParam::Wrap(std::move(interface_ptr));
605   int32_t output_value = -1;
606   ASSERT_TRUE(ptr->Echo(42, &output_value));
607   EXPECT_EQ(42, output_value);
608 }
609 
SEQUENCED_TASK_RUNNER_TYPED_TEST(SyncMethodOnSequenceCommonTest,ReenteredBySyncMethodBinding)610 SEQUENCED_TASK_RUNNER_TYPED_TEST(SyncMethodOnSequenceCommonTest,
611                                  ReenteredBySyncMethodBinding) {
612   // Test that an interface pointer waiting for a sync call response can be
613   // reentered by a binding serving sync methods on the same thread.
614 
615   int32_t output_value = -1;
616   ASSERT_TRUE(this->ptr_->Echo(42, &output_value));
617   EXPECT_EQ(42, output_value);
618   this->Done();
619 }
620 
TYPED_TEST(SyncMethodCommonTest,InterfacePtrDestroyedDuringSyncCall)621 TYPED_TEST(SyncMethodCommonTest, InterfacePtrDestroyedDuringSyncCall) {
622   // Test that it won't result in crash or hang if an interface pointer is
623   // destroyed while it is waiting for a sync call response.
624 
625   using Interface = typename TypeParam::Interface;
626   InterfacePtr<Interface> interface_ptr;
627   ImplTypeFor<Interface> impl(MakeRequest(&interface_ptr));
628   auto ptr = TypeParam::Wrap(std::move(interface_ptr));
629   impl.set_ping_handler([&ptr](const TestSync::PingCallback& callback) {
630     ptr.reset();
631     callback.Run();
632   });
633   ASSERT_FALSE(ptr->Ping());
634 }
635 
SEQUENCED_TASK_RUNNER_TYPED_TEST(SyncMethodOnSequenceCommonTest,InterfacePtrDestroyedDuringSyncCall)636 SEQUENCED_TASK_RUNNER_TYPED_TEST(SyncMethodOnSequenceCommonTest,
637                                  InterfacePtrDestroyedDuringSyncCall) {
638   // Test that it won't result in crash or hang if an interface pointer is
639   // destroyed while it is waiting for a sync call response.
640 
641   auto* ptr = &this->ptr_;
642   this->impl_->set_ping_handler([ptr](const TestSync::PingCallback& callback) {
643     ptr->reset();
644     callback.Run();
645   });
646   ASSERT_FALSE(this->ptr_->Ping());
647   this->Done();
648 }
649 
TYPED_TEST(SyncMethodCommonTest,BindingDestroyedDuringSyncCall)650 TYPED_TEST(SyncMethodCommonTest, BindingDestroyedDuringSyncCall) {
651   // Test that it won't result in crash or hang if a binding is
652   // closed (and therefore the message pipe handle is closed) while the
653   // corresponding interface pointer is waiting for a sync call response.
654 
655   using Interface = typename TypeParam::Interface;
656   InterfacePtr<Interface> interface_ptr;
657   ImplTypeFor<Interface> impl(MakeRequest(&interface_ptr));
658   auto ptr = TypeParam::Wrap(std::move(interface_ptr));
659   impl.set_ping_handler([&impl](const TestSync::PingCallback& callback) {
660     impl.binding()->Close();
661     callback.Run();
662   });
663   ASSERT_FALSE(ptr->Ping());
664 }
665 
SEQUENCED_TASK_RUNNER_TYPED_TEST(SyncMethodOnSequenceCommonTest,BindingDestroyedDuringSyncCall)666 SEQUENCED_TASK_RUNNER_TYPED_TEST(SyncMethodOnSequenceCommonTest,
667                                  BindingDestroyedDuringSyncCall) {
668   // Test that it won't result in crash or hang if a binding is
669   // closed (and therefore the message pipe handle is closed) while the
670   // corresponding interface pointer is waiting for a sync call response.
671 
672   auto& impl = *this->impl_;
673   this->impl_->set_ping_handler(
674       [&impl](const TestSync::PingCallback& callback) {
675         impl.binding()->Close();
676         callback.Run();
677       });
678   ASSERT_FALSE(this->ptr_->Ping());
679   this->Done();
680 }
681 
TYPED_TEST(SyncMethodCommonTest,NestedSyncCallsWithInOrderResponses)682 TYPED_TEST(SyncMethodCommonTest, NestedSyncCallsWithInOrderResponses) {
683   // Test that we can call a sync method on an interface ptr, while there is
684   // already a sync call ongoing. The responses arrive in order.
685 
686   using Interface = typename TypeParam::Interface;
687   InterfacePtr<Interface> interface_ptr;
688   ImplTypeFor<Interface> impl(MakeRequest(&interface_ptr));
689   auto ptr = TypeParam::Wrap(std::move(interface_ptr));
690 
691   // The same variable is used to store the output of the two sync calls, in
692   // order to test that responses are handled in the correct order.
693   int32_t result_value = -1;
694 
695   bool first_call = true;
696   impl.set_echo_handler([&first_call, &ptr, &result_value](
697       int32_t value, const TestSync::EchoCallback& callback) {
698     if (first_call) {
699       first_call = false;
700       ASSERT_TRUE(ptr->Echo(456, &result_value));
701       EXPECT_EQ(456, result_value);
702     }
703     callback.Run(value);
704   });
705 
706   ASSERT_TRUE(ptr->Echo(123, &result_value));
707   EXPECT_EQ(123, result_value);
708 }
709 
SEQUENCED_TASK_RUNNER_TYPED_TEST(SyncMethodOnSequenceCommonTest,NestedSyncCallsWithInOrderResponses)710 SEQUENCED_TASK_RUNNER_TYPED_TEST(SyncMethodOnSequenceCommonTest,
711                                  NestedSyncCallsWithInOrderResponses) {
712   // Test that we can call a sync method on an interface ptr, while there is
713   // already a sync call ongoing. The responses arrive in order.
714 
715   // The same variable is used to store the output of the two sync calls, in
716   // order to test that responses are handled in the correct order.
717   int32_t result_value = -1;
718 
719   bool first_call = true;
720   auto& ptr = this->ptr_;
721   auto& impl = *this->impl_;
722   impl.set_echo_handler(
723       [&first_call, &ptr, &result_value](
724           int32_t value, const TestSync::EchoCallback& callback) {
725         if (first_call) {
726           first_call = false;
727           ASSERT_TRUE(ptr->Echo(456, &result_value));
728           EXPECT_EQ(456, result_value);
729         }
730         callback.Run(value);
731       });
732 
733   ASSERT_TRUE(ptr->Echo(123, &result_value));
734   EXPECT_EQ(123, result_value);
735   this->Done();
736 }
737 
TYPED_TEST(SyncMethodCommonTest,NestedSyncCallsWithOutOfOrderResponses)738 TYPED_TEST(SyncMethodCommonTest, NestedSyncCallsWithOutOfOrderResponses) {
739   // Test that we can call a sync method on an interface ptr, while there is
740   // already a sync call ongoing. The responses arrive out of order.
741 
742   using Interface = typename TypeParam::Interface;
743   InterfacePtr<Interface> interface_ptr;
744   ImplTypeFor<Interface> impl(MakeRequest(&interface_ptr));
745   auto ptr = TypeParam::Wrap(std::move(interface_ptr));
746 
747   // The same variable is used to store the output of the two sync calls, in
748   // order to test that responses are handled in the correct order.
749   int32_t result_value = -1;
750 
751   bool first_call = true;
752   impl.set_echo_handler([&first_call, &ptr, &result_value](
753       int32_t value, const TestSync::EchoCallback& callback) {
754     callback.Run(value);
755     if (first_call) {
756       first_call = false;
757       ASSERT_TRUE(ptr->Echo(456, &result_value));
758       EXPECT_EQ(456, result_value);
759     }
760   });
761 
762   ASSERT_TRUE(ptr->Echo(123, &result_value));
763   EXPECT_EQ(123, result_value);
764 }
765 
SEQUENCED_TASK_RUNNER_TYPED_TEST(SyncMethodOnSequenceCommonTest,NestedSyncCallsWithOutOfOrderResponses)766 SEQUENCED_TASK_RUNNER_TYPED_TEST(SyncMethodOnSequenceCommonTest,
767                                  NestedSyncCallsWithOutOfOrderResponses) {
768   // Test that we can call a sync method on an interface ptr, while there is
769   // already a sync call ongoing. The responses arrive out of order.
770 
771   // The same variable is used to store the output of the two sync calls, in
772   // order to test that responses are handled in the correct order.
773   int32_t result_value = -1;
774 
775   bool first_call = true;
776   auto& ptr = this->ptr_;
777   auto& impl = *this->impl_;
778   impl.set_echo_handler(
779       [&first_call, &ptr, &result_value](
780           int32_t value, const TestSync::EchoCallback& callback) {
781         callback.Run(value);
782         if (first_call) {
783           first_call = false;
784           ASSERT_TRUE(ptr->Echo(456, &result_value));
785           EXPECT_EQ(456, result_value);
786         }
787       });
788 
789   ASSERT_TRUE(ptr->Echo(123, &result_value));
790   EXPECT_EQ(123, result_value);
791   this->Done();
792 }
793 
TYPED_TEST(SyncMethodCommonTest,AsyncResponseQueuedDuringSyncCall)794 TYPED_TEST(SyncMethodCommonTest, AsyncResponseQueuedDuringSyncCall) {
795   // Test that while an interface pointer is waiting for the response to a sync
796   // call, async responses are queued until the sync call completes.
797 
798   using Interface = typename TypeParam::Interface;
799   InterfacePtr<Interface> interface_ptr;
800   ImplTypeFor<Interface> impl(MakeRequest(&interface_ptr));
801   auto ptr = TypeParam::Wrap(std::move(interface_ptr));
802 
803   int32_t async_echo_request_value = -1;
804   TestSync::AsyncEchoCallback async_echo_request_callback;
805   base::RunLoop run_loop1;
806   impl.set_async_echo_handler(
807       [&async_echo_request_value, &async_echo_request_callback, &run_loop1](
808           int32_t value, const TestSync::AsyncEchoCallback& callback) {
809         async_echo_request_value = value;
810         async_echo_request_callback = callback;
811         run_loop1.Quit();
812       });
813 
814   bool async_echo_response_dispatched = false;
815   base::RunLoop run_loop2;
816   ptr->AsyncEcho(
817       123,
818       BindAsyncEchoCallback(
819          [&async_echo_response_dispatched, &run_loop2](int32_t result) {
820            async_echo_response_dispatched = true;
821            EXPECT_EQ(123, result);
822            run_loop2.Quit();
823          }));
824   // Run until the AsyncEcho request reaches the service side.
825   run_loop1.Run();
826 
827   impl.set_echo_handler(
828       [&async_echo_request_value, &async_echo_request_callback](
829           int32_t value, const TestSync::EchoCallback& callback) {
830         // Send back the async response first.
831         EXPECT_FALSE(async_echo_request_callback.is_null());
832         async_echo_request_callback.Run(async_echo_request_value);
833 
834         callback.Run(value);
835       });
836 
837   int32_t result_value = -1;
838   ASSERT_TRUE(ptr->Echo(456, &result_value));
839   EXPECT_EQ(456, result_value);
840 
841   // Although the AsyncEcho response arrives before the Echo response, it should
842   // be queued and not yet dispatched.
843   EXPECT_FALSE(async_echo_response_dispatched);
844 
845   // Run until the AsyncEcho response is dispatched.
846   run_loop2.Run();
847 
848   EXPECT_TRUE(async_echo_response_dispatched);
849 }
850 
SEQUENCED_TASK_RUNNER_TYPED_TEST_F(SyncMethodOnSequenceCommonTest,AsyncResponseQueuedDuringSyncCall)851 SEQUENCED_TASK_RUNNER_TYPED_TEST_F(SyncMethodOnSequenceCommonTest,
852                                    AsyncResponseQueuedDuringSyncCall) {
853   // Test that while an interface pointer is waiting for the response to a sync
854   // call, async responses are queued until the sync call completes.
855 
856   void Run() override {
857     this->impl_->set_async_echo_handler(
858         [this](int32_t value, const TestSync::AsyncEchoCallback& callback) {
859           async_echo_request_value_ = value;
860           async_echo_request_callback_ = callback;
861           OnAsyncEchoReceived();
862         });
863 
864     this->ptr_->AsyncEcho(123, BindAsyncEchoCallback([this](int32_t result) {
865                             async_echo_response_dispatched_ = true;
866                             EXPECT_EQ(123, result);
867                             EXPECT_TRUE(async_echo_response_dispatched_);
868                             this->Done();
869                           }));
870   }
871 
872   // Called when the AsyncEcho request reaches the service side.
873   void OnAsyncEchoReceived() {
874     this->impl_->set_echo_handler(
875         [this](int32_t value, const TestSync::EchoCallback& callback) {
876           // Send back the async response first.
877           EXPECT_FALSE(async_echo_request_callback_.is_null());
878           async_echo_request_callback_.Run(async_echo_request_value_);
879 
880           callback.Run(value);
881         });
882 
883     int32_t result_value = -1;
884     ASSERT_TRUE(this->ptr_->Echo(456, &result_value));
885     EXPECT_EQ(456, result_value);
886 
887     // Although the AsyncEcho response arrives before the Echo response, it
888     // should be queued and not yet dispatched.
889     EXPECT_FALSE(async_echo_response_dispatched_);
890   }
891 
892   int32_t async_echo_request_value_ = -1;
893   TestSync::AsyncEchoCallback async_echo_request_callback_;
894   bool async_echo_response_dispatched_ = false;
895 };
896 
TYPED_TEST(SyncMethodCommonTest,AsyncRequestQueuedDuringSyncCall)897 TYPED_TEST(SyncMethodCommonTest, AsyncRequestQueuedDuringSyncCall) {
898   // Test that while an interface pointer is waiting for the response to a sync
899   // call, async requests for a binding running on the same thread are queued
900   // until the sync call completes.
901 
902   using Interface = typename TypeParam::Interface;
903   InterfacePtr<Interface> interface_ptr;
904   ImplTypeFor<Interface> impl(MakeRequest(&interface_ptr));
905   auto ptr = TypeParam::Wrap(std::move(interface_ptr));
906 
907   bool async_echo_request_dispatched = false;
908   impl.set_async_echo_handler([&async_echo_request_dispatched](
909       int32_t value, const TestSync::AsyncEchoCallback& callback) {
910     async_echo_request_dispatched = true;
911     callback.Run(value);
912   });
913 
914   bool async_echo_response_dispatched = false;
915   base::RunLoop run_loop;
916   ptr->AsyncEcho(
917       123,
918       BindAsyncEchoCallback(
919          [&async_echo_response_dispatched, &run_loop](int32_t result) {
920            async_echo_response_dispatched = true;
921            EXPECT_EQ(123, result);
922            run_loop.Quit();
923          }));
924 
925   impl.set_echo_handler([&async_echo_request_dispatched](
926       int32_t value, const TestSync::EchoCallback& callback) {
927     // Although the AsyncEcho request is sent before the Echo request, it
928     // shouldn't be dispatched yet at this point, because there is an ongoing
929     // sync call on the same thread.
930     EXPECT_FALSE(async_echo_request_dispatched);
931     callback.Run(value);
932   });
933 
934   int32_t result_value = -1;
935   ASSERT_TRUE(ptr->Echo(456, &result_value));
936   EXPECT_EQ(456, result_value);
937 
938   // Although the AsyncEcho request is sent before the Echo request, it
939   // shouldn't be dispatched yet.
940   EXPECT_FALSE(async_echo_request_dispatched);
941 
942   // Run until the AsyncEcho response is dispatched.
943   run_loop.Run();
944 
945   EXPECT_TRUE(async_echo_response_dispatched);
946 }
947 
SEQUENCED_TASK_RUNNER_TYPED_TEST_F(SyncMethodOnSequenceCommonTest,AsyncRequestQueuedDuringSyncCall)948 SEQUENCED_TASK_RUNNER_TYPED_TEST_F(SyncMethodOnSequenceCommonTest,
949                                    AsyncRequestQueuedDuringSyncCall) {
950   // Test that while an interface pointer is waiting for the response to a sync
951   // call, async requests for a binding running on the same thread are queued
952   // until the sync call completes.
953   void Run() override {
954     this->impl_->set_async_echo_handler(
955         [this](int32_t value, const TestSync::AsyncEchoCallback& callback) {
956           async_echo_request_dispatched_ = true;
957           callback.Run(value);
958         });
959 
960     this->ptr_->AsyncEcho(123, BindAsyncEchoCallback([this](int32_t result) {
961                             EXPECT_EQ(123, result);
962                             this->Done();
963                           }));
964 
965     this->impl_->set_echo_handler(
966         [this](int32_t value, const TestSync::EchoCallback& callback) {
967           // Although the AsyncEcho request is sent before the Echo request, it
968           // shouldn't be dispatched yet at this point, because there is an
969           // ongoing
970           // sync call on the same thread.
971           EXPECT_FALSE(async_echo_request_dispatched_);
972           callback.Run(value);
973         });
974 
975     int32_t result_value = -1;
976     ASSERT_TRUE(this->ptr_->Echo(456, &result_value));
977     EXPECT_EQ(456, result_value);
978 
979     // Although the AsyncEcho request is sent before the Echo request, it
980     // shouldn't be dispatched yet.
981     EXPECT_FALSE(async_echo_request_dispatched_);
982   }
983   bool async_echo_request_dispatched_ = false;
984 };
985 
TYPED_TEST(SyncMethodCommonTest,QueuedMessagesProcessedBeforeErrorNotification)986 TYPED_TEST(SyncMethodCommonTest,
987            QueuedMessagesProcessedBeforeErrorNotification) {
988   // Test that while an interface pointer is waiting for the response to a sync
989   // call, async responses are queued. If the message pipe is disconnected
990   // before the queued messages are processed, the connection error
991   // notification is delayed until all the queued messages are processed.
992 
993   // ThreadSafeInterfacePtr doesn't guarantee that messages are delivered before
994   // error notifications, so skip it for this test.
995   if (TypeParam::kIsThreadSafeInterfacePtrTest)
996     return;
997 
998   using Interface = typename TypeParam::Interface;
999   InterfacePtr<Interface> ptr;
1000   ImplTypeFor<Interface> impl(MakeRequest(&ptr));
1001 
1002   int32_t async_echo_request_value = -1;
1003   TestSync::AsyncEchoCallback async_echo_request_callback;
1004   base::RunLoop run_loop1;
1005   impl.set_async_echo_handler(
1006       [&async_echo_request_value, &async_echo_request_callback, &run_loop1](
1007           int32_t value, const TestSync::AsyncEchoCallback& callback) {
1008         async_echo_request_value = value;
1009         async_echo_request_callback = callback;
1010         run_loop1.Quit();
1011       });
1012 
1013   bool async_echo_response_dispatched = false;
1014   bool connection_error_dispatched = false;
1015   base::RunLoop run_loop2;
1016   ptr->AsyncEcho(123, BindAsyncEchoCallback([&async_echo_response_dispatched,
1017                                              &connection_error_dispatched, &ptr,
1018                                              &run_loop2](int32_t result) {
1019                    async_echo_response_dispatched = true;
1020                    // At this point, error notification should not be dispatched
1021                    // yet.
1022                    EXPECT_FALSE(connection_error_dispatched);
1023                    EXPECT_FALSE(ptr.encountered_error());
1024                    EXPECT_EQ(123, result);
1025                    run_loop2.Quit();
1026                  }));
1027   // Run until the AsyncEcho request reaches the service side.
1028   run_loop1.Run();
1029 
1030   impl.set_echo_handler(
1031       [&impl, &async_echo_request_value, &async_echo_request_callback](
1032           int32_t value, const TestSync::EchoCallback& callback) {
1033         // Send back the async response first.
1034         EXPECT_FALSE(async_echo_request_callback.is_null());
1035         async_echo_request_callback.Run(async_echo_request_value);
1036 
1037         impl.binding()->Close();
1038       });
1039 
1040   base::RunLoop run_loop3;
1041   ptr.set_connection_error_handler(base::Bind(&SetFlagAndRunClosure,
1042                                               &connection_error_dispatched,
1043                                               run_loop3.QuitClosure()));
1044 
1045   int32_t result_value = -1;
1046   ASSERT_FALSE(ptr->Echo(456, &result_value));
1047   EXPECT_EQ(-1, result_value);
1048   ASSERT_FALSE(connection_error_dispatched);
1049   EXPECT_FALSE(ptr.encountered_error());
1050 
1051   // Although the AsyncEcho response arrives before the Echo response, it should
1052   // be queued and not yet dispatched.
1053   EXPECT_FALSE(async_echo_response_dispatched);
1054 
1055   // Run until the AsyncEcho response is dispatched.
1056   run_loop2.Run();
1057 
1058   EXPECT_TRUE(async_echo_response_dispatched);
1059 
1060   // Run until the error notification is dispatched.
1061   run_loop3.Run();
1062 
1063   ASSERT_TRUE(connection_error_dispatched);
1064   EXPECT_TRUE(ptr.encountered_error());
1065 }
1066 
SEQUENCED_TASK_RUNNER_TYPED_TEST_F(SyncMethodOnSequenceCommonTest,QueuedMessagesProcessedBeforeErrorNotification)1067 SEQUENCED_TASK_RUNNER_TYPED_TEST_F(
1068     SyncMethodOnSequenceCommonTest,
1069     QueuedMessagesProcessedBeforeErrorNotification) {
1070   // Test that while an interface pointer is waiting for the response to a sync
1071   // call, async responses are queued. If the message pipe is disconnected
1072   // before the queued messages are processed, the connection error
1073   // notification is delayed until all the queued messages are processed.
1074 
1075   void Run() override {
1076     this->impl_->set_async_echo_handler(
1077         [this](int32_t value, const TestSync::AsyncEchoCallback& callback) {
1078           OnAsyncEchoReachedService(value, callback);
1079         });
1080 
1081     this->ptr_->AsyncEcho(123, BindAsyncEchoCallback([this](int32_t result) {
1082                             async_echo_response_dispatched_ = true;
1083                             // At this point, error notification should not be
1084                             // dispatched
1085                             // yet.
1086                             EXPECT_FALSE(connection_error_dispatched_);
1087                             EXPECT_FALSE(this->ptr_.encountered_error());
1088                             EXPECT_EQ(123, result);
1089                             EXPECT_TRUE(async_echo_response_dispatched_);
1090                           }));
1091   }
1092 
1093   void OnAsyncEchoReachedService(int32_t value,
1094                                  const TestSync::AsyncEchoCallback& callback) {
1095     async_echo_request_value_ = value;
1096     async_echo_request_callback_ = callback;
1097     this->impl_->set_echo_handler(
1098         [this](int32_t value, const TestSync::EchoCallback& callback) {
1099           // Send back the async response first.
1100           EXPECT_FALSE(async_echo_request_callback_.is_null());
1101           async_echo_request_callback_.Run(async_echo_request_value_);
1102 
1103           this->impl_->binding()->Close();
1104         });
1105 
1106     this->ptr_.set_connection_error_handler(
1107         base::Bind(&SetFlagAndRunClosure, &connection_error_dispatched_,
1108                    LambdaBinder<>::BindLambda(
1109                        [this]() { OnErrorNotificationDispatched(); })));
1110 
1111     int32_t result_value = -1;
1112     ASSERT_FALSE(this->ptr_->Echo(456, &result_value));
1113     EXPECT_EQ(-1, result_value);
1114     ASSERT_FALSE(connection_error_dispatched_);
1115     EXPECT_FALSE(this->ptr_.encountered_error());
1116 
1117     // Although the AsyncEcho response arrives before the Echo response, it
1118     // should
1119     // be queued and not yet dispatched.
1120     EXPECT_FALSE(async_echo_response_dispatched_);
1121   }
1122 
1123   void OnErrorNotificationDispatched() {
1124     ASSERT_TRUE(connection_error_dispatched_);
1125     EXPECT_TRUE(this->ptr_.encountered_error());
1126     this->Done();
1127   }
1128 
1129   int32_t async_echo_request_value_ = -1;
1130   TestSync::AsyncEchoCallback async_echo_request_callback_;
1131   bool async_echo_response_dispatched_ = false;
1132   bool connection_error_dispatched_ = false;
1133 };
1134 
TYPED_TEST(SyncMethodCommonTest,InvalidMessageDuringSyncCall)1135 TYPED_TEST(SyncMethodCommonTest, InvalidMessageDuringSyncCall) {
1136   // Test that while an interface pointer is waiting for the response to a sync
1137   // call, an invalid incoming message will disconnect the message pipe, cause
1138   // the sync call to return false, and run the connection error handler
1139   // asynchronously.
1140 
1141   using Interface = typename TypeParam::Interface;
1142   MessagePipe pipe;
1143 
1144   InterfacePtr<Interface> interface_ptr;
1145   interface_ptr.Bind(InterfacePtrInfo<Interface>(std::move(pipe.handle0), 0u));
1146   auto ptr = TypeParam::Wrap(std::move(interface_ptr));
1147 
1148   MessagePipeHandle raw_binding_handle = pipe.handle1.get();
1149   ImplTypeFor<Interface> impl(
1150       InterfaceRequest<Interface>(std::move(pipe.handle1)));
1151 
1152   impl.set_echo_handler([&raw_binding_handle](
1153       int32_t value, const TestSync::EchoCallback& callback) {
1154     // Write a 1-byte message, which is considered invalid.
1155     char invalid_message = 0;
1156     MojoResult result =
1157         WriteMessageRaw(raw_binding_handle, &invalid_message, 1u, nullptr, 0u,
1158                         MOJO_WRITE_MESSAGE_FLAG_NONE);
1159     ASSERT_EQ(MOJO_RESULT_OK, result);
1160     callback.Run(value);
1161   });
1162 
1163   bool connection_error_dispatched = false;
1164   base::RunLoop run_loop;
1165   // ThreadSafeInterfacePtr doesn't support setting connection error handlers.
1166   if (!TypeParam::kIsThreadSafeInterfacePtrTest) {
1167     ptr.set_connection_error_handler(base::Bind(&SetFlagAndRunClosure,
1168                                                 &connection_error_dispatched,
1169                                                 run_loop.QuitClosure()));
1170   }
1171 
1172   int32_t result_value = -1;
1173   ASSERT_FALSE(ptr->Echo(456, &result_value));
1174   EXPECT_EQ(-1, result_value);
1175   ASSERT_FALSE(connection_error_dispatched);
1176 
1177   if (!TypeParam::kIsThreadSafeInterfacePtrTest) {
1178     run_loop.Run();
1179     ASSERT_TRUE(connection_error_dispatched);
1180   }
1181 }
1182 
SEQUENCED_TASK_RUNNER_TYPED_TEST_F(SyncMethodOnSequenceCommonTest,InvalidMessageDuringSyncCall)1183 SEQUENCED_TASK_RUNNER_TYPED_TEST_F(SyncMethodOnSequenceCommonTest,
1184                                    InvalidMessageDuringSyncCall) {
1185   // Test that while an interface pointer is waiting for the response to a sync
1186   // call, an invalid incoming message will disconnect the message pipe, cause
1187   // the sync call to return false, and run the connection error handler
1188   // asynchronously.
1189 
1190   void Run() override {
1191     MessagePipe pipe;
1192 
1193     using InterfaceType = typename TypeParam::Interface;
1194     this->ptr_.Bind(
1195         InterfacePtrInfo<InterfaceType>(std::move(pipe.handle0), 0u));
1196 
1197     MessagePipeHandle raw_binding_handle = pipe.handle1.get();
1198     this->impl_ = std::make_unique<ImplTypeFor<InterfaceType>>(
1199         InterfaceRequest<InterfaceType>(std::move(pipe.handle1)));
1200 
1201     this->impl_->set_echo_handler(
1202         [raw_binding_handle](int32_t value,
1203                              const TestSync::EchoCallback& callback) {
1204           // Write a 1-byte message, which is considered invalid.
1205           char invalid_message = 0;
1206           MojoResult result =
1207               WriteMessageRaw(raw_binding_handle, &invalid_message, 1u, nullptr,
1208                               0u, MOJO_WRITE_MESSAGE_FLAG_NONE);
1209           ASSERT_EQ(MOJO_RESULT_OK, result);
1210           callback.Run(value);
1211         });
1212 
1213     this->ptr_.set_connection_error_handler(
1214         LambdaBinder<>::BindLambda([this]() {
1215           connection_error_dispatched_ = true;
1216           this->Done();
1217         }));
1218 
1219     int32_t result_value = -1;
1220     ASSERT_FALSE(this->ptr_->Echo(456, &result_value));
1221     EXPECT_EQ(-1, result_value);
1222     ASSERT_FALSE(connection_error_dispatched_);
1223   }
1224   bool connection_error_dispatched_ = false;
1225 };
1226 
TEST_F(SyncMethodAssociatedTest,ReenteredBySyncMethodAssoBindingOfSameRouter)1227 TEST_F(SyncMethodAssociatedTest, ReenteredBySyncMethodAssoBindingOfSameRouter) {
1228   // Test that an interface pointer waiting for a sync call response can be
1229   // reentered by an associated binding serving sync methods on the same thread.
1230   // The associated binding belongs to the same MultiplexRouter as the waiting
1231   // interface pointer.
1232 
1233   TestSyncAssociatedImpl opposite_asso_impl(std::move(opposite_asso_request_));
1234   TestSyncAssociatedPtr opposite_asso_ptr;
1235   opposite_asso_ptr.Bind(std::move(opposite_asso_ptr_info_));
1236 
1237   master_impl_->set_echo_handler([&opposite_asso_ptr](
1238       int32_t value, const TestSyncMaster::EchoCallback& callback) {
1239     int32_t result_value = -1;
1240 
1241     ASSERT_TRUE(opposite_asso_ptr->Echo(123, &result_value));
1242     EXPECT_EQ(123, result_value);
1243     callback.Run(value);
1244   });
1245 
1246   int32_t result_value = -1;
1247   ASSERT_TRUE(master_ptr_->Echo(456, &result_value));
1248   EXPECT_EQ(456, result_value);
1249 }
1250 
TEST_F(SyncMethodAssociatedTest,ReenteredBySyncMethodAssoBindingOfDifferentRouter)1251 TEST_F(SyncMethodAssociatedTest,
1252        ReenteredBySyncMethodAssoBindingOfDifferentRouter) {
1253   // Test that an interface pointer waiting for a sync call response can be
1254   // reentered by an associated binding serving sync methods on the same thread.
1255   // The associated binding belongs to a different MultiplexRouter as the
1256   // waiting interface pointer.
1257 
1258   TestSyncAssociatedImpl asso_impl(std::move(asso_request_));
1259   TestSyncAssociatedPtr asso_ptr;
1260   asso_ptr.Bind(std::move(asso_ptr_info_));
1261 
1262   master_impl_->set_echo_handler(
1263       [&asso_ptr](int32_t value, const TestSyncMaster::EchoCallback& callback) {
1264         int32_t result_value = -1;
1265 
1266         ASSERT_TRUE(asso_ptr->Echo(123, &result_value));
1267         EXPECT_EQ(123, result_value);
1268         callback.Run(value);
1269       });
1270 
1271   int32_t result_value = -1;
1272   ASSERT_TRUE(master_ptr_->Echo(456, &result_value));
1273   EXPECT_EQ(456, result_value);
1274 }
1275 
1276 // TODO(yzshen): Add more tests related to associated interfaces.
1277 
1278 }  // namespace
1279 }  // namespace test
1280 }  // namespace mojo
1281