1 // Copyright 2015 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 <stddef.h>
6 #include <stdint.h>
7 #include <algorithm>
8 #include <utility>
9
10 #include "base/bind.h"
11 #include "base/callback.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/run_loop.h"
14 #include "base/single_thread_task_runner.h"
15 #include "base/threading/thread.h"
16 #include "base/threading/thread_task_runner_handle.h"
17 #include "mojo/public/cpp/bindings/associated_binding.h"
18 #include "mojo/public/cpp/bindings/associated_group.h"
19 #include "mojo/public/cpp/bindings/associated_interface_ptr.h"
20 #include "mojo/public/cpp/bindings/associated_interface_ptr_info.h"
21 #include "mojo/public/cpp/bindings/associated_interface_request.h"
22 #include "mojo/public/cpp/bindings/binding.h"
23 #include "mojo/public/cpp/bindings/lib/multiplex_router.h"
24 #include "mojo/public/interfaces/bindings/tests/test_associated_interfaces.mojom.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26
27 namespace mojo {
28 namespace test {
29 namespace {
30
31 using mojo::internal::MultiplexRouter;
32
33 class IntegerSenderImpl : public IntegerSender {
34 public:
IntegerSenderImpl(AssociatedInterfaceRequest<IntegerSender> request)35 explicit IntegerSenderImpl(AssociatedInterfaceRequest<IntegerSender> request)
36 : binding_(this, std::move(request)) {}
37
~IntegerSenderImpl()38 ~IntegerSenderImpl() override {}
39
set_notify_send_method_called(const base::Callback<void (int32_t)> & callback)40 void set_notify_send_method_called(
41 const base::Callback<void(int32_t)>& callback) {
42 notify_send_method_called_ = callback;
43 }
44
Echo(int32_t value,const EchoCallback & callback)45 void Echo(int32_t value, const EchoCallback& callback) override {
46 callback.Run(value);
47 }
Send(int32_t value)48 void Send(int32_t value) override { notify_send_method_called_.Run(value); }
49
binding()50 AssociatedBinding<IntegerSender>* binding() { return &binding_; }
51
set_connection_error_handler(const base::Closure & handler)52 void set_connection_error_handler(const base::Closure& handler) {
53 binding_.set_connection_error_handler(handler);
54 }
55
56 private:
57 AssociatedBinding<IntegerSender> binding_;
58 base::Callback<void(int32_t)> notify_send_method_called_;
59 };
60
61 class IntegerSenderConnectionImpl : public IntegerSenderConnection {
62 public:
IntegerSenderConnectionImpl(InterfaceRequest<IntegerSenderConnection> request)63 explicit IntegerSenderConnectionImpl(
64 InterfaceRequest<IntegerSenderConnection> request)
65 : binding_(this, std::move(request)) {}
66
~IntegerSenderConnectionImpl()67 ~IntegerSenderConnectionImpl() override {}
68
GetSender(AssociatedInterfaceRequest<IntegerSender> sender)69 void GetSender(AssociatedInterfaceRequest<IntegerSender> sender) override {
70 IntegerSenderImpl* sender_impl = new IntegerSenderImpl(std::move(sender));
71 sender_impl->set_connection_error_handler(
72 base::Bind(&DeleteSender, sender_impl));
73 }
74
AsyncGetSender(const AsyncGetSenderCallback & callback)75 void AsyncGetSender(const AsyncGetSenderCallback& callback) override {
76 AssociatedInterfaceRequest<IntegerSender> request;
77 IntegerSenderAssociatedPtrInfo ptr_info;
78 binding_.associated_group()->CreateAssociatedInterface(
79 AssociatedGroup::WILL_PASS_PTR, &ptr_info, &request);
80 GetSender(std::move(request));
81 callback.Run(std::move(ptr_info));
82 }
83
binding()84 Binding<IntegerSenderConnection>* binding() { return &binding_; }
85
86 private:
DeleteSender(IntegerSenderImpl * sender)87 static void DeleteSender(IntegerSenderImpl* sender) { delete sender; }
88
89 Binding<IntegerSenderConnection> binding_;
90 };
91
92 class AssociatedInterfaceTest : public testing::Test {
93 public:
AssociatedInterfaceTest()94 AssociatedInterfaceTest() {}
~AssociatedInterfaceTest()95 ~AssociatedInterfaceTest() override { base::RunLoop().RunUntilIdle(); }
96
PumpMessages()97 void PumpMessages() { base::RunLoop().RunUntilIdle(); }
98
99 template <typename T>
EmulatePassingAssociatedPtrInfo(AssociatedInterfacePtrInfo<T> ptr_info,scoped_refptr<MultiplexRouter> target)100 AssociatedInterfacePtrInfo<T> EmulatePassingAssociatedPtrInfo(
101 AssociatedInterfacePtrInfo<T> ptr_info,
102 scoped_refptr<MultiplexRouter> target) {
103 ScopedInterfaceEndpointHandle handle = ptr_info.PassHandle();
104 CHECK(!handle.is_local());
105 return AssociatedInterfacePtrInfo<T>(
106 target->CreateLocalEndpointHandle(handle.release()),
107 ptr_info.version());
108 }
109
110 template <typename T>
EmulatePassingAssociatedRequest(AssociatedInterfaceRequest<T> request,scoped_refptr<MultiplexRouter> target)111 AssociatedInterfaceRequest<T> EmulatePassingAssociatedRequest(
112 AssociatedInterfaceRequest<T> request,
113 scoped_refptr<MultiplexRouter> target) {
114 ScopedInterfaceEndpointHandle handle = request.PassHandle();
115 CHECK(!handle.is_local());
116 return MakeAssociatedRequest<T>(
117 target->CreateLocalEndpointHandle(handle.release()));
118 }
119
120 // Okay to call from any thread.
QuitRunLoop(base::RunLoop * run_loop)121 void QuitRunLoop(base::RunLoop* run_loop) {
122 if (loop_.task_runner()->BelongsToCurrentThread()) {
123 run_loop->Quit();
124 } else {
125 loop_.task_runner()->PostTask(
126 FROM_HERE,
127 base::Bind(&AssociatedInterfaceTest::QuitRunLoop,
128 base::Unretained(this), base::Unretained(run_loop)));
129 }
130 }
131
132 private:
133 base::MessageLoop loop_;
134 };
135
DoSetFlagAndRunClosure(bool * flag,const base::Closure & closure)136 void DoSetFlagAndRunClosure(bool* flag, const base::Closure& closure) {
137 *flag = true;
138 closure.Run();
139 }
140
DoExpectValueSetFlagAndRunClosure(int32_t expected_value,bool * flag,const base::Closure & closure,int32_t value)141 void DoExpectValueSetFlagAndRunClosure(int32_t expected_value,
142 bool* flag,
143 const base::Closure& closure,
144 int32_t value) {
145 EXPECT_EQ(expected_value, value);
146 DoSetFlagAndRunClosure(flag, closure);
147 }
148
SetFlagAndRunClosure(bool * flag,const base::Closure & closure)149 base::Closure SetFlagAndRunClosure(bool* flag, const base::Closure& closure) {
150 return base::Bind(&DoSetFlagAndRunClosure, flag, closure);
151 }
152
ExpectValueSetFlagAndRunClosure(int32_t expected_value,bool * flag,const base::Closure & closure)153 base::Callback<void(int32_t)> ExpectValueSetFlagAndRunClosure(
154 int32_t expected_value,
155 bool* flag,
156 const base::Closure& closure) {
157 return base::Bind(
158 &DoExpectValueSetFlagAndRunClosure, expected_value, flag, closure);
159 }
160
TEST_F(AssociatedInterfaceTest,InterfacesAtBothEnds)161 TEST_F(AssociatedInterfaceTest, InterfacesAtBothEnds) {
162 // Bind to the same pipe two associated interfaces, whose implementation lives
163 // at different ends. Test that the two don't interfere with each other.
164
165 MessagePipe pipe;
166 scoped_refptr<MultiplexRouter> router0(new MultiplexRouter(
167 true, std::move(pipe.handle0), base::ThreadTaskRunnerHandle::Get()));
168 scoped_refptr<MultiplexRouter> router1(new MultiplexRouter(
169 false, std::move(pipe.handle1), base::ThreadTaskRunnerHandle::Get()));
170
171 AssociatedInterfaceRequest<IntegerSender> request;
172 IntegerSenderAssociatedPtrInfo ptr_info;
173
174 router0->CreateAssociatedGroup()->CreateAssociatedInterface(
175 AssociatedGroup::WILL_PASS_PTR, &ptr_info, &request);
176 ptr_info = EmulatePassingAssociatedPtrInfo(std::move(ptr_info), router1);
177
178 IntegerSenderImpl impl0(std::move(request));
179 AssociatedInterfacePtr<IntegerSender> ptr0;
180 ptr0.Bind(std::move(ptr_info));
181
182 router0->CreateAssociatedGroup()->CreateAssociatedInterface(
183 AssociatedGroup::WILL_PASS_REQUEST, &ptr_info, &request);
184 request = EmulatePassingAssociatedRequest(std::move(request), router1);
185
186 IntegerSenderImpl impl1(std::move(request));
187 AssociatedInterfacePtr<IntegerSender> ptr1;
188 ptr1.Bind(std::move(ptr_info));
189
190 base::RunLoop run_loop, run_loop2;
191 bool ptr0_callback_run = false;
192 ptr0->Echo(123, ExpectValueSetFlagAndRunClosure(123, &ptr0_callback_run,
193 run_loop.QuitClosure()));
194
195 bool ptr1_callback_run = false;
196 ptr1->Echo(456, ExpectValueSetFlagAndRunClosure(456, &ptr1_callback_run,
197 run_loop2.QuitClosure()));
198
199 run_loop.Run();
200 run_loop2.Run();
201 EXPECT_TRUE(ptr0_callback_run);
202 EXPECT_TRUE(ptr1_callback_run);
203
204 bool ptr0_error_callback_run = false;
205 base::RunLoop run_loop3;
206 ptr0.set_connection_error_handler(
207 SetFlagAndRunClosure(&ptr0_error_callback_run, run_loop3.QuitClosure()));
208
209 impl0.binding()->Close();
210 run_loop3.Run();
211 EXPECT_TRUE(ptr0_error_callback_run);
212
213 bool impl1_error_callback_run = false;
214 base::RunLoop run_loop4;
215 impl1.binding()->set_connection_error_handler(
216 SetFlagAndRunClosure(&impl1_error_callback_run, run_loop4.QuitClosure()));
217
218 ptr1.reset();
219 run_loop4.Run();
220 EXPECT_TRUE(impl1_error_callback_run);
221 }
222
223 class TestSender {
224 public:
TestSender()225 TestSender()
226 : sender_thread_("TestSender"),
227 next_sender_(nullptr),
228 max_value_to_send_(-1) {
229 sender_thread_.Start();
230 }
231
232 // The following three methods are called on the corresponding sender thread.
SetUp(IntegerSenderAssociatedPtrInfo ptr_info,TestSender * next_sender,int32_t max_value_to_send)233 void SetUp(IntegerSenderAssociatedPtrInfo ptr_info,
234 TestSender* next_sender,
235 int32_t max_value_to_send) {
236 CHECK(sender_thread_.task_runner()->BelongsToCurrentThread());
237
238 ptr_.Bind(std::move(ptr_info));
239 next_sender_ = next_sender ? next_sender : this;
240 max_value_to_send_ = max_value_to_send;
241 }
242
Send(int32_t value)243 void Send(int32_t value) {
244 CHECK(sender_thread_.task_runner()->BelongsToCurrentThread());
245
246 if (value > max_value_to_send_)
247 return;
248
249 ptr_->Send(value);
250
251 next_sender_->sender_thread()->task_runner()->PostTask(
252 FROM_HERE,
253 base::Bind(&TestSender::Send, base::Unretained(next_sender_), ++value));
254 }
255
TearDown()256 void TearDown() {
257 CHECK(sender_thread_.task_runner()->BelongsToCurrentThread());
258
259 ptr_.reset();
260 }
261
sender_thread()262 base::Thread* sender_thread() { return &sender_thread_; }
263
264 private:
265 base::Thread sender_thread_;
266 TestSender* next_sender_;
267 int32_t max_value_to_send_;
268
269 AssociatedInterfacePtr<IntegerSender> ptr_;
270 };
271
272 class TestReceiver {
273 public:
TestReceiver()274 TestReceiver() : receiver_thread_("TestReceiver"), expected_calls_(0) {
275 receiver_thread_.Start();
276 }
277
SetUp(AssociatedInterfaceRequest<IntegerSender> request0,AssociatedInterfaceRequest<IntegerSender> request1,size_t expected_calls,const base::Closure & notify_finish)278 void SetUp(AssociatedInterfaceRequest<IntegerSender> request0,
279 AssociatedInterfaceRequest<IntegerSender> request1,
280 size_t expected_calls,
281 const base::Closure& notify_finish) {
282 CHECK(receiver_thread_.task_runner()->BelongsToCurrentThread());
283
284 impl0_.reset(new IntegerSenderImpl(std::move(request0)));
285 impl0_->set_notify_send_method_called(
286 base::Bind(&TestReceiver::SendMethodCalled, base::Unretained(this)));
287 impl1_.reset(new IntegerSenderImpl(std::move(request1)));
288 impl1_->set_notify_send_method_called(
289 base::Bind(&TestReceiver::SendMethodCalled, base::Unretained(this)));
290
291 expected_calls_ = expected_calls;
292 notify_finish_ = notify_finish;
293 }
294
TearDown()295 void TearDown() {
296 CHECK(receiver_thread_.task_runner()->BelongsToCurrentThread());
297
298 impl0_.reset();
299 impl1_.reset();
300 }
301
receiver_thread()302 base::Thread* receiver_thread() { return &receiver_thread_; }
values() const303 const std::vector<int32_t>& values() const { return values_; }
304
305 private:
SendMethodCalled(int32_t value)306 void SendMethodCalled(int32_t value) {
307 values_.push_back(value);
308
309 if (values_.size() >= expected_calls_)
310 notify_finish_.Run();
311 }
312
313 base::Thread receiver_thread_;
314 size_t expected_calls_;
315
316 std::unique_ptr<IntegerSenderImpl> impl0_;
317 std::unique_ptr<IntegerSenderImpl> impl1_;
318
319 std::vector<int32_t> values_;
320
321 base::Closure notify_finish_;
322 };
323
324 class NotificationCounter {
325 public:
NotificationCounter(size_t total_count,const base::Closure & notify_finish)326 NotificationCounter(size_t total_count, const base::Closure& notify_finish)
327 : total_count_(total_count),
328 current_count_(0),
329 notify_finish_(notify_finish) {}
330
~NotificationCounter()331 ~NotificationCounter() {}
332
333 // Okay to call from any thread.
OnGotNotification()334 void OnGotNotification() {
335 bool finshed = false;
336 {
337 base::AutoLock locker(lock_);
338 CHECK_LT(current_count_, total_count_);
339 current_count_++;
340 finshed = current_count_ == total_count_;
341 }
342
343 if (finshed)
344 notify_finish_.Run();
345 }
346
347 private:
348 base::Lock lock_;
349 const size_t total_count_;
350 size_t current_count_;
351 base::Closure notify_finish_;
352 };
353
TEST_F(AssociatedInterfaceTest,MultiThreadAccess)354 TEST_F(AssociatedInterfaceTest, MultiThreadAccess) {
355 // Set up four associated interfaces on a message pipe. Use the inteface
356 // pointers on four threads in parallel; run the interface implementations on
357 // two threads. Test that multi-threaded access works.
358
359 const int32_t kMaxValue = 1000;
360 MessagePipe pipe;
361 scoped_refptr<MultiplexRouter> router0(new MultiplexRouter(
362 true, std::move(pipe.handle0), base::ThreadTaskRunnerHandle::Get()));
363 scoped_refptr<MultiplexRouter> router1(new MultiplexRouter(
364 false, std::move(pipe.handle1), base::ThreadTaskRunnerHandle::Get()));
365
366 AssociatedInterfaceRequest<IntegerSender> requests[4];
367 IntegerSenderAssociatedPtrInfo ptr_infos[4];
368
369 for (size_t i = 0; i < 4; ++i) {
370 router0->CreateAssociatedGroup()->CreateAssociatedInterface(
371 AssociatedGroup::WILL_PASS_PTR, &ptr_infos[i], &requests[i]);
372 ptr_infos[i] =
373 EmulatePassingAssociatedPtrInfo(std::move(ptr_infos[i]), router1);
374 }
375
376 TestSender senders[4];
377 for (size_t i = 0; i < 4; ++i) {
378 senders[i].sender_thread()->task_runner()->PostTask(
379 FROM_HERE, base::Bind(&TestSender::SetUp, base::Unretained(&senders[i]),
380 base::Passed(&ptr_infos[i]), nullptr,
381 kMaxValue * (i + 1) / 4));
382 }
383
384 base::RunLoop run_loop;
385 TestReceiver receivers[2];
386 NotificationCounter counter(
387 2, base::Bind(&AssociatedInterfaceTest::QuitRunLoop,
388 base::Unretained(this), base::Unretained(&run_loop)));
389 for (size_t i = 0; i < 2; ++i) {
390 receivers[i].receiver_thread()->task_runner()->PostTask(
391 FROM_HERE,
392 base::Bind(&TestReceiver::SetUp, base::Unretained(&receivers[i]),
393 base::Passed(&requests[2 * i]),
394 base::Passed(&requests[2 * i + 1]),
395 static_cast<size_t>(kMaxValue / 2),
396 base::Bind(&NotificationCounter::OnGotNotification,
397 base::Unretained(&counter))));
398 }
399
400 for (size_t i = 0; i < 4; ++i) {
401 senders[i].sender_thread()->task_runner()->PostTask(
402 FROM_HERE, base::Bind(&TestSender::Send, base::Unretained(&senders[i]),
403 kMaxValue * i / 4 + 1));
404 }
405
406 run_loop.Run();
407
408 for (size_t i = 0; i < 4; ++i) {
409 base::RunLoop run_loop;
410 senders[i].sender_thread()->task_runner()->PostTaskAndReply(
411 FROM_HERE,
412 base::Bind(&TestSender::TearDown, base::Unretained(&senders[i])),
413 base::Bind(&AssociatedInterfaceTest::QuitRunLoop,
414 base::Unretained(this), base::Unretained(&run_loop)));
415 run_loop.Run();
416 }
417
418 for (size_t i = 0; i < 2; ++i) {
419 base::RunLoop run_loop;
420 receivers[i].receiver_thread()->task_runner()->PostTaskAndReply(
421 FROM_HERE,
422 base::Bind(&TestReceiver::TearDown, base::Unretained(&receivers[i])),
423 base::Bind(&AssociatedInterfaceTest::QuitRunLoop,
424 base::Unretained(this), base::Unretained(&run_loop)));
425 run_loop.Run();
426 }
427
428 EXPECT_EQ(static_cast<size_t>(kMaxValue / 2), receivers[0].values().size());
429 EXPECT_EQ(static_cast<size_t>(kMaxValue / 2), receivers[1].values().size());
430
431 std::vector<int32_t> all_values;
432 all_values.insert(all_values.end(), receivers[0].values().begin(),
433 receivers[0].values().end());
434 all_values.insert(all_values.end(), receivers[1].values().begin(),
435 receivers[1].values().end());
436
437 std::sort(all_values.begin(), all_values.end());
438 for (size_t i = 0; i < all_values.size(); ++i)
439 ASSERT_EQ(static_cast<int32_t>(i + 1), all_values[i]);
440 }
441
TEST_F(AssociatedInterfaceTest,FIFO)442 TEST_F(AssociatedInterfaceTest, FIFO) {
443 // Set up four associated interfaces on a message pipe. Use the inteface
444 // pointers on four threads; run the interface implementations on two threads.
445 // Take turns to make calls using the four pointers. Test that FIFO-ness is
446 // preserved.
447
448 const int32_t kMaxValue = 100;
449 MessagePipe pipe;
450 scoped_refptr<MultiplexRouter> router0(new MultiplexRouter(
451 true, std::move(pipe.handle0), base::ThreadTaskRunnerHandle::Get()));
452 scoped_refptr<MultiplexRouter> router1(new MultiplexRouter(
453 false, std::move(pipe.handle1), base::ThreadTaskRunnerHandle::Get()));
454
455 AssociatedInterfaceRequest<IntegerSender> requests[4];
456 IntegerSenderAssociatedPtrInfo ptr_infos[4];
457
458 for (size_t i = 0; i < 4; ++i) {
459 router0->CreateAssociatedGroup()->CreateAssociatedInterface(
460 AssociatedGroup::WILL_PASS_PTR, &ptr_infos[i], &requests[i]);
461 ptr_infos[i] =
462 EmulatePassingAssociatedPtrInfo(std::move(ptr_infos[i]), router1);
463 }
464
465 TestSender senders[4];
466 for (size_t i = 0; i < 4; ++i) {
467 senders[i].sender_thread()->task_runner()->PostTask(
468 FROM_HERE,
469 base::Bind(&TestSender::SetUp, base::Unretained(&senders[i]),
470 base::Passed(&ptr_infos[i]),
471 base::Unretained(&senders[(i + 1) % 4]), kMaxValue));
472 }
473
474 base::RunLoop run_loop;
475 TestReceiver receivers[2];
476 NotificationCounter counter(
477 2, base::Bind(&AssociatedInterfaceTest::QuitRunLoop,
478 base::Unretained(this), base::Unretained(&run_loop)));
479 for (size_t i = 0; i < 2; ++i) {
480 receivers[i].receiver_thread()->task_runner()->PostTask(
481 FROM_HERE,
482 base::Bind(&TestReceiver::SetUp, base::Unretained(&receivers[i]),
483 base::Passed(&requests[2 * i]),
484 base::Passed(&requests[2 * i + 1]),
485 static_cast<size_t>(kMaxValue / 2),
486 base::Bind(&NotificationCounter::OnGotNotification,
487 base::Unretained(&counter))));
488 }
489
490 senders[0].sender_thread()->task_runner()->PostTask(
491 FROM_HERE,
492 base::Bind(&TestSender::Send, base::Unretained(&senders[0]), 1));
493
494 run_loop.Run();
495
496 for (size_t i = 0; i < 4; ++i) {
497 base::RunLoop run_loop;
498 senders[i].sender_thread()->task_runner()->PostTaskAndReply(
499 FROM_HERE,
500 base::Bind(&TestSender::TearDown, base::Unretained(&senders[i])),
501 base::Bind(&AssociatedInterfaceTest::QuitRunLoop,
502 base::Unretained(this), base::Unretained(&run_loop)));
503 run_loop.Run();
504 }
505
506 for (size_t i = 0; i < 2; ++i) {
507 base::RunLoop run_loop;
508 receivers[i].receiver_thread()->task_runner()->PostTaskAndReply(
509 FROM_HERE,
510 base::Bind(&TestReceiver::TearDown, base::Unretained(&receivers[i])),
511 base::Bind(&AssociatedInterfaceTest::QuitRunLoop,
512 base::Unretained(this), base::Unretained(&run_loop)));
513 run_loop.Run();
514 }
515
516 EXPECT_EQ(static_cast<size_t>(kMaxValue / 2), receivers[0].values().size());
517 EXPECT_EQ(static_cast<size_t>(kMaxValue / 2), receivers[1].values().size());
518
519 for (size_t i = 0; i < 2; ++i) {
520 for (size_t j = 1; j < receivers[i].values().size(); ++j)
521 EXPECT_LT(receivers[i].values()[j - 1], receivers[i].values()[j]);
522 }
523 }
524
CaptureInt32(int32_t * storage,const base::Closure & closure,int32_t value)525 void CaptureInt32(int32_t* storage,
526 const base::Closure& closure,
527 int32_t value) {
528 *storage = value;
529 closure.Run();
530 }
531
CaptureSenderPtrInfo(IntegerSenderAssociatedPtr * storage,const base::Closure & closure,IntegerSenderAssociatedPtrInfo info)532 void CaptureSenderPtrInfo(IntegerSenderAssociatedPtr* storage,
533 const base::Closure& closure,
534 IntegerSenderAssociatedPtrInfo info) {
535 storage->Bind(std::move(info));
536 closure.Run();
537 }
538
TEST_F(AssociatedInterfaceTest,PassAssociatedInterfaces)539 TEST_F(AssociatedInterfaceTest, PassAssociatedInterfaces) {
540 IntegerSenderConnectionPtr connection_ptr;
541 IntegerSenderConnectionImpl connection(GetProxy(&connection_ptr));
542
543 IntegerSenderAssociatedPtr sender0;
544 connection_ptr->GetSender(
545 GetProxy(&sender0, connection_ptr.associated_group()));
546
547 int32_t echoed_value = 0;
548 base::RunLoop run_loop;
549 sender0->Echo(123, base::Bind(&CaptureInt32, &echoed_value,
550 run_loop.QuitClosure()));
551 run_loop.Run();
552 EXPECT_EQ(123, echoed_value);
553
554 IntegerSenderAssociatedPtr sender1;
555 base::RunLoop run_loop2;
556 connection_ptr->AsyncGetSender(
557 base::Bind(&CaptureSenderPtrInfo, &sender1, run_loop2.QuitClosure()));
558 run_loop2.Run();
559 EXPECT_TRUE(sender1);
560
561 base::RunLoop run_loop3;
562 sender1->Echo(456, base::Bind(&CaptureInt32, &echoed_value,
563 run_loop3.QuitClosure()));
564 run_loop3.Run();
565 EXPECT_EQ(456, echoed_value);
566 }
567
TEST_F(AssociatedInterfaceTest,BindingWaitAndPauseWhenNoAssociatedInterfaces)568 TEST_F(AssociatedInterfaceTest, BindingWaitAndPauseWhenNoAssociatedInterfaces) {
569 IntegerSenderConnectionPtr connection_ptr;
570 IntegerSenderConnectionImpl connection(GetProxy(&connection_ptr));
571
572 IntegerSenderAssociatedPtr sender0;
573 connection_ptr->GetSender(
574 GetProxy(&sender0, connection_ptr.associated_group()));
575
576 EXPECT_FALSE(connection.binding()->HasAssociatedInterfaces());
577 // There are no associated interfaces running on the pipe yet. It is okay to
578 // pause.
579 connection.binding()->PauseIncomingMethodCallProcessing();
580 connection.binding()->ResumeIncomingMethodCallProcessing();
581
582 // There are no associated interfaces running on the pipe yet. It is okay to
583 // wait.
584 EXPECT_TRUE(connection.binding()->WaitForIncomingMethodCall());
585
586 // The previous wait has dispatched the GetSender request message, therefore
587 // an associated interface has been set up on the pipe. It is not allowed to
588 // wait or pause.
589 EXPECT_TRUE(connection.binding()->HasAssociatedInterfaces());
590 }
591
592 } // namespace
593 } // namespace test
594 } // namespace mojo
595