• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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