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