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/callback_helpers.h"
13 #include "base/memory/ptr_util.h"
14 #include "base/run_loop.h"
15 #include "base/single_thread_task_runner.h"
16 #include "base/synchronization/waitable_event.h"
17 #include "base/task_scheduler/post_task.h"
18 #include "base/test/scoped_task_environment.h"
19 #include "base/threading/sequenced_task_runner_handle.h"
20 #include "base/threading/thread.h"
21 #include "base/threading/thread_task_runner_handle.h"
22 #include "mojo/public/cpp/bindings/associated_binding.h"
23 #include "mojo/public/cpp/bindings/associated_interface_ptr.h"
24 #include "mojo/public/cpp/bindings/associated_interface_ptr_info.h"
25 #include "mojo/public/cpp/bindings/associated_interface_request.h"
26 #include "mojo/public/cpp/bindings/binding.h"
27 #include "mojo/public/cpp/bindings/lib/multiplex_router.h"
28 #include "mojo/public/cpp/bindings/strong_binding.h"
29 #include "mojo/public/cpp/bindings/thread_safe_interface_ptr.h"
30 #include "mojo/public/interfaces/bindings/tests/ping_service.mojom.h"
31 #include "mojo/public/interfaces/bindings/tests/test_associated_interfaces.mojom.h"
32 #include "testing/gtest/include/gtest/gtest.h"
33 
34 namespace mojo {
35 namespace test {
36 namespace {
37 
38 using mojo::internal::MultiplexRouter;
39 
40 class IntegerSenderImpl : public IntegerSender {
41  public:
IntegerSenderImpl(AssociatedInterfaceRequest<IntegerSender> request)42   explicit IntegerSenderImpl(AssociatedInterfaceRequest<IntegerSender> request)
43       : binding_(this, std::move(request)) {}
44 
~IntegerSenderImpl()45   ~IntegerSenderImpl() override {}
46 
set_notify_send_method_called(const base::Callback<void (int32_t)> & callback)47   void set_notify_send_method_called(
48       const base::Callback<void(int32_t)>& callback) {
49     notify_send_method_called_ = callback;
50   }
51 
Echo(int32_t value,const EchoCallback & callback)52   void Echo(int32_t value, const EchoCallback& callback) override {
53     callback.Run(value);
54   }
Send(int32_t value)55   void Send(int32_t value) override { notify_send_method_called_.Run(value); }
56 
binding()57   AssociatedBinding<IntegerSender>* binding() { return &binding_; }
58 
set_connection_error_handler(const base::Closure & handler)59   void set_connection_error_handler(const base::Closure& handler) {
60     binding_.set_connection_error_handler(handler);
61   }
62 
63  private:
64   AssociatedBinding<IntegerSender> binding_;
65   base::Callback<void(int32_t)> notify_send_method_called_;
66 };
67 
68 class IntegerSenderConnectionImpl : public IntegerSenderConnection {
69  public:
IntegerSenderConnectionImpl(InterfaceRequest<IntegerSenderConnection> request)70   explicit IntegerSenderConnectionImpl(
71       InterfaceRequest<IntegerSenderConnection> request)
72       : binding_(this, std::move(request)) {}
73 
~IntegerSenderConnectionImpl()74   ~IntegerSenderConnectionImpl() override {}
75 
GetSender(AssociatedInterfaceRequest<IntegerSender> sender)76   void GetSender(AssociatedInterfaceRequest<IntegerSender> sender) override {
77     IntegerSenderImpl* sender_impl = new IntegerSenderImpl(std::move(sender));
78     sender_impl->set_connection_error_handler(
79         base::Bind(&DeleteSender, sender_impl));
80   }
81 
AsyncGetSender(const AsyncGetSenderCallback & callback)82   void AsyncGetSender(const AsyncGetSenderCallback& callback) override {
83     IntegerSenderAssociatedPtrInfo ptr_info;
84     auto request = MakeRequest(&ptr_info);
85     GetSender(std::move(request));
86     callback.Run(std::move(ptr_info));
87   }
88 
binding()89   Binding<IntegerSenderConnection>* binding() { return &binding_; }
90 
91  private:
DeleteSender(IntegerSenderImpl * sender)92   static void DeleteSender(IntegerSenderImpl* sender) { delete sender; }
93 
94   Binding<IntegerSenderConnection> binding_;
95 };
96 
97 class AssociatedInterfaceTest : public testing::Test {
98  public:
AssociatedInterfaceTest()99   AssociatedInterfaceTest()
100       : main_runner_(base::ThreadTaskRunnerHandle::Get()) {}
~AssociatedInterfaceTest()101   ~AssociatedInterfaceTest() override { base::RunLoop().RunUntilIdle(); }
102 
PumpMessages()103   void PumpMessages() { base::RunLoop().RunUntilIdle(); }
104 
105   template <typename T>
EmulatePassingAssociatedPtrInfo(AssociatedInterfacePtrInfo<T> ptr_info,scoped_refptr<MultiplexRouter> source,scoped_refptr<MultiplexRouter> target)106   AssociatedInterfacePtrInfo<T> EmulatePassingAssociatedPtrInfo(
107       AssociatedInterfacePtrInfo<T> ptr_info,
108       scoped_refptr<MultiplexRouter> source,
109       scoped_refptr<MultiplexRouter> target) {
110     ScopedInterfaceEndpointHandle handle = ptr_info.PassHandle();
111     CHECK(handle.pending_association());
112     auto id = source->AssociateInterface(std::move(handle));
113     return AssociatedInterfacePtrInfo<T>(target->CreateLocalEndpointHandle(id),
114                                          ptr_info.version());
115   }
116 
CreateRouterPair(scoped_refptr<MultiplexRouter> * router0,scoped_refptr<MultiplexRouter> * router1)117   void CreateRouterPair(scoped_refptr<MultiplexRouter>* router0,
118                         scoped_refptr<MultiplexRouter>* router1) {
119     MessagePipe pipe;
120     *router0 = new MultiplexRouter(std::move(pipe.handle0),
121                                    MultiplexRouter::MULTI_INTERFACE, true,
122                                    main_runner_);
123     *router1 = new MultiplexRouter(std::move(pipe.handle1),
124                                    MultiplexRouter::MULTI_INTERFACE, false,
125                                    main_runner_);
126   }
127 
CreateIntegerSenderWithExistingRouters(scoped_refptr<MultiplexRouter> router0,IntegerSenderAssociatedPtrInfo * ptr_info0,scoped_refptr<MultiplexRouter> router1,IntegerSenderAssociatedRequest * request1)128   void CreateIntegerSenderWithExistingRouters(
129       scoped_refptr<MultiplexRouter> router0,
130       IntegerSenderAssociatedPtrInfo* ptr_info0,
131       scoped_refptr<MultiplexRouter> router1,
132       IntegerSenderAssociatedRequest* request1) {
133     *request1 = MakeRequest(ptr_info0);
134     *ptr_info0 = EmulatePassingAssociatedPtrInfo(std::move(*ptr_info0), router1,
135                                                  router0);
136   }
137 
CreateIntegerSender(IntegerSenderAssociatedPtrInfo * ptr_info,IntegerSenderAssociatedRequest * request)138   void CreateIntegerSender(IntegerSenderAssociatedPtrInfo* ptr_info,
139                            IntegerSenderAssociatedRequest* request) {
140     scoped_refptr<MultiplexRouter> router0;
141     scoped_refptr<MultiplexRouter> router1;
142     CreateRouterPair(&router0, &router1);
143     CreateIntegerSenderWithExistingRouters(router1, ptr_info, router0, request);
144   }
145 
146   // Okay to call from any thread.
QuitRunLoop(base::RunLoop * run_loop)147   void QuitRunLoop(base::RunLoop* run_loop) {
148     if (main_runner_->RunsTasksInCurrentSequence()) {
149       run_loop->Quit();
150     } else {
151       main_runner_->PostTask(
152           FROM_HERE,
153           base::Bind(&AssociatedInterfaceTest::QuitRunLoop,
154                      base::Unretained(this), base::Unretained(run_loop)));
155     }
156   }
157 
158  private:
159   base::test::ScopedTaskEnvironment task_environment;
160   scoped_refptr<base::SequencedTaskRunner> main_runner_;
161 };
162 
DoSetFlagAndRunClosure(bool * flag,const base::Closure & closure)163 void DoSetFlagAndRunClosure(bool* flag, const base::Closure& closure) {
164   *flag = true;
165   closure.Run();
166 }
167 
DoExpectValueSetFlagAndRunClosure(int32_t expected_value,bool * flag,const base::Closure & closure,int32_t value)168 void DoExpectValueSetFlagAndRunClosure(int32_t expected_value,
169                                        bool* flag,
170                                        const base::Closure& closure,
171                                        int32_t value) {
172   EXPECT_EQ(expected_value, value);
173   DoSetFlagAndRunClosure(flag, closure);
174 }
175 
SetFlagAndRunClosure(bool * flag,const base::Closure & closure)176 base::Closure SetFlagAndRunClosure(bool* flag, const base::Closure& closure) {
177   return base::Bind(&DoSetFlagAndRunClosure, flag, closure);
178 }
179 
ExpectValueSetFlagAndRunClosure(int32_t expected_value,bool * flag,const base::Closure & closure)180 base::Callback<void(int32_t)> ExpectValueSetFlagAndRunClosure(
181     int32_t expected_value,
182     bool* flag,
183     const base::Closure& closure) {
184   return base::Bind(
185       &DoExpectValueSetFlagAndRunClosure, expected_value, flag, closure);
186 }
187 
Fail()188 void Fail() {
189   FAIL() << "Unexpected connection error";
190 }
191 
TEST_F(AssociatedInterfaceTest,InterfacesAtBothEnds)192 TEST_F(AssociatedInterfaceTest, InterfacesAtBothEnds) {
193   // Bind to the same pipe two associated interfaces, whose implementation lives
194   // at different ends. Test that the two don't interfere with each other.
195 
196   scoped_refptr<MultiplexRouter> router0;
197   scoped_refptr<MultiplexRouter> router1;
198   CreateRouterPair(&router0, &router1);
199 
200   AssociatedInterfaceRequest<IntegerSender> request;
201   IntegerSenderAssociatedPtrInfo ptr_info;
202   CreateIntegerSenderWithExistingRouters(router1, &ptr_info, router0, &request);
203 
204   IntegerSenderImpl impl0(std::move(request));
205   AssociatedInterfacePtr<IntegerSender> ptr0;
206   ptr0.Bind(std::move(ptr_info));
207 
208   CreateIntegerSenderWithExistingRouters(router0, &ptr_info, router1, &request);
209 
210   IntegerSenderImpl impl1(std::move(request));
211   AssociatedInterfacePtr<IntegerSender> ptr1;
212   ptr1.Bind(std::move(ptr_info));
213 
214   base::RunLoop run_loop, run_loop2;
215   bool ptr0_callback_run = false;
216   ptr0->Echo(123, ExpectValueSetFlagAndRunClosure(123, &ptr0_callback_run,
217                                                   run_loop.QuitClosure()));
218 
219   bool ptr1_callback_run = false;
220   ptr1->Echo(456, ExpectValueSetFlagAndRunClosure(456, &ptr1_callback_run,
221                                                   run_loop2.QuitClosure()));
222 
223   run_loop.Run();
224   run_loop2.Run();
225   EXPECT_TRUE(ptr0_callback_run);
226   EXPECT_TRUE(ptr1_callback_run);
227 
228   bool ptr0_error_callback_run = false;
229   base::RunLoop run_loop3;
230   ptr0.set_connection_error_handler(
231       SetFlagAndRunClosure(&ptr0_error_callback_run, run_loop3.QuitClosure()));
232 
233   impl0.binding()->Close();
234   run_loop3.Run();
235   EXPECT_TRUE(ptr0_error_callback_run);
236 
237   bool impl1_error_callback_run = false;
238   base::RunLoop run_loop4;
239   impl1.binding()->set_connection_error_handler(
240       SetFlagAndRunClosure(&impl1_error_callback_run, run_loop4.QuitClosure()));
241 
242   ptr1.reset();
243   run_loop4.Run();
244   EXPECT_TRUE(impl1_error_callback_run);
245 }
246 
247 class TestSender {
248  public:
TestSender()249   TestSender()
250       : task_runner_(base::CreateSequencedTaskRunnerWithTraits({})),
251         next_sender_(nullptr),
252         max_value_to_send_(-1) {}
253 
254   // The following three methods are called on the corresponding sender thread.
SetUp(IntegerSenderAssociatedPtrInfo ptr_info,TestSender * next_sender,int32_t max_value_to_send)255   void SetUp(IntegerSenderAssociatedPtrInfo ptr_info,
256              TestSender* next_sender,
257              int32_t max_value_to_send) {
258     CHECK(task_runner()->RunsTasksInCurrentSequence());
259 
260     ptr_.Bind(std::move(ptr_info));
261     next_sender_ = next_sender ? next_sender : this;
262     max_value_to_send_ = max_value_to_send;
263   }
264 
Send(int32_t value)265   void Send(int32_t value) {
266     CHECK(task_runner()->RunsTasksInCurrentSequence());
267 
268     if (value > max_value_to_send_)
269       return;
270 
271     ptr_->Send(value);
272 
273     next_sender_->task_runner()->PostTask(
274         FROM_HERE,
275         base::Bind(&TestSender::Send, base::Unretained(next_sender_), ++value));
276   }
277 
TearDown()278   void TearDown() {
279     CHECK(task_runner()->RunsTasksInCurrentSequence());
280 
281     ptr_.reset();
282   }
283 
task_runner()284   base::SequencedTaskRunner* task_runner() { return task_runner_.get(); }
285 
286  private:
287   scoped_refptr<base::SequencedTaskRunner> task_runner_;
288   TestSender* next_sender_;
289   int32_t max_value_to_send_;
290 
291   AssociatedInterfacePtr<IntegerSender> ptr_;
292 };
293 
294 class TestReceiver {
295  public:
TestReceiver()296   TestReceiver()
297       : task_runner_(base::CreateSequencedTaskRunnerWithTraits({})),
298         expected_calls_(0) {}
299 
SetUp(AssociatedInterfaceRequest<IntegerSender> request0,AssociatedInterfaceRequest<IntegerSender> request1,size_t expected_calls,const base::Closure & notify_finish)300   void SetUp(AssociatedInterfaceRequest<IntegerSender> request0,
301              AssociatedInterfaceRequest<IntegerSender> request1,
302              size_t expected_calls,
303              const base::Closure& notify_finish) {
304     CHECK(task_runner()->RunsTasksInCurrentSequence());
305 
306     impl0_.reset(new IntegerSenderImpl(std::move(request0)));
307     impl0_->set_notify_send_method_called(
308         base::Bind(&TestReceiver::SendMethodCalled, base::Unretained(this)));
309     impl1_.reset(new IntegerSenderImpl(std::move(request1)));
310     impl1_->set_notify_send_method_called(
311         base::Bind(&TestReceiver::SendMethodCalled, base::Unretained(this)));
312 
313     expected_calls_ = expected_calls;
314     notify_finish_ = notify_finish;
315   }
316 
TearDown()317   void TearDown() {
318     CHECK(task_runner()->RunsTasksInCurrentSequence());
319 
320     impl0_.reset();
321     impl1_.reset();
322   }
323 
task_runner()324   base::SequencedTaskRunner* task_runner() { return task_runner_.get(); }
values() const325   const std::vector<int32_t>& values() const { return values_; }
326 
327  private:
SendMethodCalled(int32_t value)328   void SendMethodCalled(int32_t value) {
329     values_.push_back(value);
330 
331     if (values_.size() >= expected_calls_)
332       notify_finish_.Run();
333   }
334 
335   scoped_refptr<base::SequencedTaskRunner> task_runner_;
336   size_t expected_calls_;
337 
338   std::unique_ptr<IntegerSenderImpl> impl0_;
339   std::unique_ptr<IntegerSenderImpl> impl1_;
340 
341   std::vector<int32_t> values_;
342 
343   base::Closure notify_finish_;
344 };
345 
346 class NotificationCounter {
347  public:
NotificationCounter(size_t total_count,const base::Closure & notify_finish)348   NotificationCounter(size_t total_count, const base::Closure& notify_finish)
349       : total_count_(total_count),
350         current_count_(0),
351         notify_finish_(notify_finish) {}
352 
~NotificationCounter()353   ~NotificationCounter() {}
354 
355   // Okay to call from any thread.
OnGotNotification()356   void OnGotNotification() {
357     bool finshed = false;
358     {
359       base::AutoLock locker(lock_);
360       CHECK_LT(current_count_, total_count_);
361       current_count_++;
362       finshed = current_count_ == total_count_;
363     }
364 
365     if (finshed)
366       notify_finish_.Run();
367   }
368 
369  private:
370   base::Lock lock_;
371   const size_t total_count_;
372   size_t current_count_;
373   base::Closure notify_finish_;
374 };
375 
TEST_F(AssociatedInterfaceTest,MultiThreadAccess)376 TEST_F(AssociatedInterfaceTest, MultiThreadAccess) {
377   // Set up four associated interfaces on a message pipe. Use the inteface
378   // pointers on four threads in parallel; run the interface implementations on
379   // two threads. Test that multi-threaded access works.
380 
381   const int32_t kMaxValue = 1000;
382   MessagePipe pipe;
383   scoped_refptr<MultiplexRouter> router0;
384   scoped_refptr<MultiplexRouter> router1;
385   CreateRouterPair(&router0, &router1);
386 
387   AssociatedInterfaceRequest<IntegerSender> requests[4];
388   IntegerSenderAssociatedPtrInfo ptr_infos[4];
389   for (size_t i = 0; i < 4; ++i) {
390     CreateIntegerSenderWithExistingRouters(router1, &ptr_infos[i], router0,
391                                            &requests[i]);
392   }
393 
394   TestSender senders[4];
395   for (size_t i = 0; i < 4; ++i) {
396     senders[i].task_runner()->PostTask(
397         FROM_HERE, base::Bind(&TestSender::SetUp, base::Unretained(&senders[i]),
398                               base::Passed(&ptr_infos[i]), nullptr,
399                               kMaxValue * (i + 1) / 4));
400   }
401 
402   base::RunLoop run_loop;
403   TestReceiver receivers[2];
404   NotificationCounter counter(
405       2, base::Bind(&AssociatedInterfaceTest::QuitRunLoop,
406                     base::Unretained(this), base::Unretained(&run_loop)));
407   for (size_t i = 0; i < 2; ++i) {
408     receivers[i].task_runner()->PostTask(
409         FROM_HERE,
410         base::Bind(&TestReceiver::SetUp, base::Unretained(&receivers[i]),
411                    base::Passed(&requests[2 * i]),
412                    base::Passed(&requests[2 * i + 1]),
413                    static_cast<size_t>(kMaxValue / 2),
414                    base::Bind(&NotificationCounter::OnGotNotification,
415                               base::Unretained(&counter))));
416   }
417 
418   for (size_t i = 0; i < 4; ++i) {
419     senders[i].task_runner()->PostTask(
420         FROM_HERE, base::Bind(&TestSender::Send, base::Unretained(&senders[i]),
421                               kMaxValue * i / 4 + 1));
422   }
423 
424   run_loop.Run();
425 
426   for (size_t i = 0; i < 4; ++i) {
427     base::RunLoop run_loop;
428     senders[i].task_runner()->PostTaskAndReply(
429         FROM_HERE,
430         base::Bind(&TestSender::TearDown, base::Unretained(&senders[i])),
431         base::Bind(&AssociatedInterfaceTest::QuitRunLoop,
432                    base::Unretained(this), base::Unretained(&run_loop)));
433     run_loop.Run();
434   }
435 
436   for (size_t i = 0; i < 2; ++i) {
437     base::RunLoop run_loop;
438     receivers[i].task_runner()->PostTaskAndReply(
439         FROM_HERE,
440         base::Bind(&TestReceiver::TearDown, base::Unretained(&receivers[i])),
441         base::Bind(&AssociatedInterfaceTest::QuitRunLoop,
442                    base::Unretained(this), base::Unretained(&run_loop)));
443     run_loop.Run();
444   }
445 
446   EXPECT_EQ(static_cast<size_t>(kMaxValue / 2), receivers[0].values().size());
447   EXPECT_EQ(static_cast<size_t>(kMaxValue / 2), receivers[1].values().size());
448 
449   std::vector<int32_t> all_values;
450   all_values.insert(all_values.end(), receivers[0].values().begin(),
451                     receivers[0].values().end());
452   all_values.insert(all_values.end(), receivers[1].values().begin(),
453                     receivers[1].values().end());
454 
455   std::sort(all_values.begin(), all_values.end());
456   for (size_t i = 0; i < all_values.size(); ++i)
457     ASSERT_EQ(static_cast<int32_t>(i + 1), all_values[i]);
458 }
459 
TEST_F(AssociatedInterfaceTest,FIFO)460 TEST_F(AssociatedInterfaceTest, FIFO) {
461   // Set up four associated interfaces on a message pipe. Use the inteface
462   // pointers on four threads; run the interface implementations on two threads.
463   // Take turns to make calls using the four pointers. Test that FIFO-ness is
464   // preserved.
465 
466   const int32_t kMaxValue = 100;
467   MessagePipe pipe;
468   scoped_refptr<MultiplexRouter> router0;
469   scoped_refptr<MultiplexRouter> router1;
470   CreateRouterPair(&router0, &router1);
471 
472   AssociatedInterfaceRequest<IntegerSender> requests[4];
473   IntegerSenderAssociatedPtrInfo ptr_infos[4];
474   for (size_t i = 0; i < 4; ++i) {
475     CreateIntegerSenderWithExistingRouters(router1, &ptr_infos[i], router0,
476                                            &requests[i]);
477   }
478 
479   TestSender senders[4];
480   for (size_t i = 0; i < 4; ++i) {
481     senders[i].task_runner()->PostTask(
482         FROM_HERE,
483         base::Bind(&TestSender::SetUp, base::Unretained(&senders[i]),
484                    base::Passed(&ptr_infos[i]),
485                    base::Unretained(&senders[(i + 1) % 4]), kMaxValue));
486   }
487 
488   base::RunLoop run_loop;
489   TestReceiver receivers[2];
490   NotificationCounter counter(
491       2, base::Bind(&AssociatedInterfaceTest::QuitRunLoop,
492                     base::Unretained(this), base::Unretained(&run_loop)));
493   for (size_t i = 0; i < 2; ++i) {
494     receivers[i].task_runner()->PostTask(
495         FROM_HERE,
496         base::Bind(&TestReceiver::SetUp, base::Unretained(&receivers[i]),
497                    base::Passed(&requests[2 * i]),
498                    base::Passed(&requests[2 * i + 1]),
499                    static_cast<size_t>(kMaxValue / 2),
500                    base::Bind(&NotificationCounter::OnGotNotification,
501                               base::Unretained(&counter))));
502   }
503 
504   senders[0].task_runner()->PostTask(
505       FROM_HERE,
506       base::Bind(&TestSender::Send, base::Unretained(&senders[0]), 1));
507 
508   run_loop.Run();
509 
510   for (size_t i = 0; i < 4; ++i) {
511     base::RunLoop run_loop;
512     senders[i].task_runner()->PostTaskAndReply(
513         FROM_HERE,
514         base::Bind(&TestSender::TearDown, base::Unretained(&senders[i])),
515         base::Bind(&AssociatedInterfaceTest::QuitRunLoop,
516                    base::Unretained(this), base::Unretained(&run_loop)));
517     run_loop.Run();
518   }
519 
520   for (size_t i = 0; i < 2; ++i) {
521     base::RunLoop run_loop;
522     receivers[i].task_runner()->PostTaskAndReply(
523         FROM_HERE,
524         base::Bind(&TestReceiver::TearDown, base::Unretained(&receivers[i])),
525         base::Bind(&AssociatedInterfaceTest::QuitRunLoop,
526                    base::Unretained(this), base::Unretained(&run_loop)));
527     run_loop.Run();
528   }
529 
530   EXPECT_EQ(static_cast<size_t>(kMaxValue / 2), receivers[0].values().size());
531   EXPECT_EQ(static_cast<size_t>(kMaxValue / 2), receivers[1].values().size());
532 
533   for (size_t i = 0; i < 2; ++i) {
534     for (size_t j = 1; j < receivers[i].values().size(); ++j)
535       EXPECT_LT(receivers[i].values()[j - 1], receivers[i].values()[j]);
536   }
537 }
538 
CaptureInt32(int32_t * storage,const base::Closure & closure,int32_t value)539 void CaptureInt32(int32_t* storage,
540                   const base::Closure& closure,
541                   int32_t value) {
542   *storage = value;
543   closure.Run();
544 }
545 
CaptureSenderPtrInfo(IntegerSenderAssociatedPtr * storage,const base::Closure & closure,IntegerSenderAssociatedPtrInfo info)546 void CaptureSenderPtrInfo(IntegerSenderAssociatedPtr* storage,
547                           const base::Closure& closure,
548                           IntegerSenderAssociatedPtrInfo info) {
549   storage->Bind(std::move(info));
550   closure.Run();
551 }
552 
TEST_F(AssociatedInterfaceTest,PassAssociatedInterfaces)553 TEST_F(AssociatedInterfaceTest, PassAssociatedInterfaces) {
554   IntegerSenderConnectionPtr connection_ptr;
555   IntegerSenderConnectionImpl connection(MakeRequest(&connection_ptr));
556 
557   IntegerSenderAssociatedPtr sender0;
558   connection_ptr->GetSender(MakeRequest(&sender0));
559 
560   int32_t echoed_value = 0;
561   base::RunLoop run_loop;
562   sender0->Echo(123, base::Bind(&CaptureInt32, &echoed_value,
563                                 run_loop.QuitClosure()));
564   run_loop.Run();
565   EXPECT_EQ(123, echoed_value);
566 
567   IntegerSenderAssociatedPtr sender1;
568   base::RunLoop run_loop2;
569   connection_ptr->AsyncGetSender(
570       base::Bind(&CaptureSenderPtrInfo, &sender1, run_loop2.QuitClosure()));
571   run_loop2.Run();
572   EXPECT_TRUE(sender1);
573 
574   base::RunLoop run_loop3;
575   sender1->Echo(456, base::Bind(&CaptureInt32, &echoed_value,
576                                 run_loop3.QuitClosure()));
577   run_loop3.Run();
578   EXPECT_EQ(456, echoed_value);
579 }
580 
TEST_F(AssociatedInterfaceTest,BindingWaitAndPauseWhenNoAssociatedInterfaces)581 TEST_F(AssociatedInterfaceTest, BindingWaitAndPauseWhenNoAssociatedInterfaces) {
582   IntegerSenderConnectionPtr connection_ptr;
583   IntegerSenderConnectionImpl connection(MakeRequest(&connection_ptr));
584 
585   IntegerSenderAssociatedPtr sender0;
586   connection_ptr->GetSender(MakeRequest(&sender0));
587 
588   EXPECT_FALSE(connection.binding()->HasAssociatedInterfaces());
589   // There are no associated interfaces running on the pipe yet. It is okay to
590   // pause.
591   connection.binding()->PauseIncomingMethodCallProcessing();
592   connection.binding()->ResumeIncomingMethodCallProcessing();
593 
594   // There are no associated interfaces running on the pipe yet. It is okay to
595   // wait.
596   EXPECT_TRUE(connection.binding()->WaitForIncomingMethodCall());
597 
598   // The previous wait has dispatched the GetSender request message, therefore
599   // an associated interface has been set up on the pipe. It is not allowed to
600   // wait or pause.
601   EXPECT_TRUE(connection.binding()->HasAssociatedInterfaces());
602 }
603 
604 class PingServiceImpl : public PingService {
605  public:
PingServiceImpl(PingServiceAssociatedRequest request)606   explicit PingServiceImpl(PingServiceAssociatedRequest request)
607       : binding_(this, std::move(request)) {}
~PingServiceImpl()608   ~PingServiceImpl() override {}
609 
binding()610   AssociatedBinding<PingService>& binding() { return binding_; }
611 
set_ping_handler(const base::Closure & handler)612   void set_ping_handler(const base::Closure& handler) {
613     ping_handler_ = handler;
614   }
615 
616   // PingService:
Ping(const PingCallback & callback)617   void Ping(const PingCallback& callback) override {
618     if (!ping_handler_.is_null())
619       ping_handler_.Run();
620     callback.Run();
621   }
622 
623  private:
624   AssociatedBinding<PingService> binding_;
625   base::Closure ping_handler_;
626 };
627 
628 class PingProviderImpl : public AssociatedPingProvider {
629  public:
PingProviderImpl(AssociatedPingProviderRequest request)630   explicit PingProviderImpl(AssociatedPingProviderRequest request)
631       : binding_(this, std::move(request)) {}
~PingProviderImpl()632   ~PingProviderImpl() override {}
633 
634   // AssociatedPingProvider:
GetPing(PingServiceAssociatedRequest request)635   void GetPing(PingServiceAssociatedRequest request) override {
636     ping_services_.emplace_back(new PingServiceImpl(std::move(request)));
637 
638     if (expected_bindings_count_ > 0 &&
639         ping_services_.size() == expected_bindings_count_ &&
640         !quit_waiting_.is_null()) {
641       expected_bindings_count_ = 0;
642       base::ResetAndReturn(&quit_waiting_).Run();
643     }
644   }
645 
ping_services()646   std::vector<std::unique_ptr<PingServiceImpl>>& ping_services() {
647     return ping_services_;
648   }
649 
WaitForBindings(size_t count)650   void WaitForBindings(size_t count) {
651     DCHECK(quit_waiting_.is_null());
652 
653     expected_bindings_count_ = count;
654     base::RunLoop loop;
655     quit_waiting_ = loop.QuitClosure();
656     loop.Run();
657   }
658 
659  private:
660   Binding<AssociatedPingProvider> binding_;
661   std::vector<std::unique_ptr<PingServiceImpl>> ping_services_;
662   size_t expected_bindings_count_ = 0;
663   base::Closure quit_waiting_;
664 };
665 
666 class CallbackFilter : public MessageReceiver {
667  public:
CallbackFilter(const base::Closure & callback)668   explicit CallbackFilter(const base::Closure& callback)
669       : callback_(callback) {}
~CallbackFilter()670   ~CallbackFilter() override {}
671 
Wrap(const base::Closure & callback)672   static std::unique_ptr<CallbackFilter> Wrap(const base::Closure& callback) {
673     return std::make_unique<CallbackFilter>(callback);
674   }
675 
676   // MessageReceiver:
Accept(Message * message)677   bool Accept(Message* message) override {
678     callback_.Run();
679     return true;
680   }
681 
682  private:
683   const base::Closure callback_;
684 };
685 
686 // Verifies that filters work as expected on associated bindings, i.e. that
687 // they're notified in order, before dispatch; and that each associated
688 // binding in a group operates with its own set of filters.
TEST_F(AssociatedInterfaceTest,BindingWithFilters)689 TEST_F(AssociatedInterfaceTest, BindingWithFilters) {
690   AssociatedPingProviderPtr provider;
691   PingProviderImpl provider_impl(MakeRequest(&provider));
692 
693   PingServiceAssociatedPtr ping_a, ping_b;
694   provider->GetPing(MakeRequest(&ping_a));
695   provider->GetPing(MakeRequest(&ping_b));
696   provider_impl.WaitForBindings(2);
697 
698   ASSERT_EQ(2u, provider_impl.ping_services().size());
699   PingServiceImpl& ping_a_impl = *provider_impl.ping_services()[0];
700   PingServiceImpl& ping_b_impl = *provider_impl.ping_services()[1];
701 
702   int a_status, b_status;
703   auto handler_helper = [] (int* a_status, int* b_status, int expected_a_status,
704                             int new_a_status, int expected_b_status,
705                             int new_b_status) {
706     EXPECT_EQ(expected_a_status, *a_status);
707     EXPECT_EQ(expected_b_status, *b_status);
708     *a_status = new_a_status;
709     *b_status = new_b_status;
710   };
711   auto create_handler = [&] (int expected_a_status, int new_a_status,
712                              int expected_b_status, int new_b_status) {
713     return base::Bind(handler_helper, &a_status, &b_status, expected_a_status,
714                       new_a_status, expected_b_status, new_b_status);
715   };
716 
717   ping_a_impl.binding().AddFilter(
718       CallbackFilter::Wrap(create_handler(0, 1, 0, 0)));
719   ping_a_impl.binding().AddFilter(
720       CallbackFilter::Wrap(create_handler(1, 2, 0, 0)));
721   ping_a_impl.set_ping_handler(create_handler(2, 3, 0, 0));
722 
723   ping_b_impl.binding().AddFilter(
724       CallbackFilter::Wrap(create_handler(3, 3, 0, 1)));
725   ping_b_impl.binding().AddFilter(
726       CallbackFilter::Wrap(create_handler(3, 3, 1, 2)));
727   ping_b_impl.set_ping_handler(create_handler(3, 3, 2, 3));
728 
729   for (int i = 0; i < 10; ++i) {
730     a_status = 0;
731     b_status = 0;
732 
733     {
734       base::RunLoop loop;
735       ping_a->Ping(loop.QuitClosure());
736       loop.Run();
737     }
738 
739     EXPECT_EQ(3, a_status);
740     EXPECT_EQ(0, b_status);
741 
742     {
743       base::RunLoop loop;
744       ping_b->Ping(loop.QuitClosure());
745       loop.Run();
746     }
747 
748     EXPECT_EQ(3, a_status);
749     EXPECT_EQ(3, b_status);
750   }
751 }
752 
TEST_F(AssociatedInterfaceTest,AssociatedPtrFlushForTesting)753 TEST_F(AssociatedInterfaceTest, AssociatedPtrFlushForTesting) {
754   AssociatedInterfaceRequest<IntegerSender> request;
755   IntegerSenderAssociatedPtrInfo ptr_info;
756   CreateIntegerSender(&ptr_info, &request);
757 
758   IntegerSenderImpl impl0(std::move(request));
759   AssociatedInterfacePtr<IntegerSender> ptr0;
760   ptr0.Bind(std::move(ptr_info));
761   ptr0.set_connection_error_handler(base::Bind(&Fail));
762 
763   bool ptr0_callback_run = false;
764   ptr0->Echo(123, ExpectValueSetFlagAndRunClosure(123, &ptr0_callback_run,
765                                                   base::DoNothing()));
766   ptr0.FlushForTesting();
767   EXPECT_TRUE(ptr0_callback_run);
768 }
769 
SetBool(bool * value)770 void SetBool(bool* value) {
771   *value = true;
772 }
773 
774 template <typename T>
SetBoolWithUnusedParameter(bool * value,T unused)775 void SetBoolWithUnusedParameter(bool* value, T unused) {
776   *value = true;
777 }
778 
TEST_F(AssociatedInterfaceTest,AssociatedPtrFlushForTestingWithClosedPeer)779 TEST_F(AssociatedInterfaceTest, AssociatedPtrFlushForTestingWithClosedPeer) {
780   AssociatedInterfaceRequest<IntegerSender> request;
781   IntegerSenderAssociatedPtrInfo ptr_info;
782   CreateIntegerSender(&ptr_info, &request);
783 
784   AssociatedInterfacePtr<IntegerSender> ptr0;
785   ptr0.Bind(std::move(ptr_info));
786   bool called = false;
787   ptr0.set_connection_error_handler(base::Bind(&SetBool, &called));
788   request = nullptr;
789 
790   ptr0.FlushForTesting();
791   EXPECT_TRUE(called);
792   ptr0.FlushForTesting();
793 }
794 
TEST_F(AssociatedInterfaceTest,AssociatedBindingFlushForTesting)795 TEST_F(AssociatedInterfaceTest, AssociatedBindingFlushForTesting) {
796   AssociatedInterfaceRequest<IntegerSender> request;
797   IntegerSenderAssociatedPtrInfo ptr_info;
798   CreateIntegerSender(&ptr_info, &request);
799 
800   IntegerSenderImpl impl0(std::move(request));
801   impl0.set_connection_error_handler(base::Bind(&Fail));
802   AssociatedInterfacePtr<IntegerSender> ptr0;
803   ptr0.Bind(std::move(ptr_info));
804 
805   bool ptr0_callback_run = false;
806   ptr0->Echo(123, ExpectValueSetFlagAndRunClosure(123, &ptr0_callback_run,
807                                                   base::DoNothing()));
808   // Because the flush is sent from the binding, it only guarantees that the
809   // request has been received, not the response. The second flush waits for the
810   // response to be received.
811   impl0.binding()->FlushForTesting();
812   impl0.binding()->FlushForTesting();
813   EXPECT_TRUE(ptr0_callback_run);
814 }
815 
TEST_F(AssociatedInterfaceTest,AssociatedBindingFlushForTestingWithClosedPeer)816 TEST_F(AssociatedInterfaceTest,
817        AssociatedBindingFlushForTestingWithClosedPeer) {
818   scoped_refptr<MultiplexRouter> router0;
819   scoped_refptr<MultiplexRouter> router1;
820   CreateRouterPair(&router0, &router1);
821 
822   AssociatedInterfaceRequest<IntegerSender> request;
823   {
824     IntegerSenderAssociatedPtrInfo ptr_info;
825     CreateIntegerSenderWithExistingRouters(router1, &ptr_info, router0,
826                                            &request);
827   }
828 
829   IntegerSenderImpl impl(std::move(request));
830   bool called = false;
831   impl.set_connection_error_handler(base::Bind(&SetBool, &called));
832   impl.binding()->FlushForTesting();
833   EXPECT_TRUE(called);
834   impl.binding()->FlushForTesting();
835 }
836 
TEST_F(AssociatedInterfaceTest,BindingFlushForTesting)837 TEST_F(AssociatedInterfaceTest, BindingFlushForTesting) {
838   IntegerSenderConnectionPtr ptr;
839   IntegerSenderConnectionImpl impl(MakeRequest(&ptr));
840   bool called = false;
841   ptr->AsyncGetSender(base::Bind(
842       &SetBoolWithUnusedParameter<IntegerSenderAssociatedPtrInfo>, &called));
843   EXPECT_FALSE(called);
844   impl.binding()->set_connection_error_handler(base::Bind(&Fail));
845   // Because the flush is sent from the binding, it only guarantees that the
846   // request has been received, not the response. The second flush waits for the
847   // response to be received.
848   impl.binding()->FlushForTesting();
849   impl.binding()->FlushForTesting();
850   EXPECT_TRUE(called);
851 }
852 
TEST_F(AssociatedInterfaceTest,BindingFlushForTestingWithClosedPeer)853 TEST_F(AssociatedInterfaceTest, BindingFlushForTestingWithClosedPeer) {
854   IntegerSenderConnectionPtr ptr;
855   IntegerSenderConnectionImpl impl(MakeRequest(&ptr));
856   bool called = false;
857   impl.binding()->set_connection_error_handler(base::Bind(&SetBool, &called));
858   ptr.reset();
859   EXPECT_FALSE(called);
860   impl.binding()->FlushForTesting();
861   EXPECT_TRUE(called);
862   impl.binding()->FlushForTesting();
863 }
864 
TEST_F(AssociatedInterfaceTest,StrongBindingFlushForTesting)865 TEST_F(AssociatedInterfaceTest, StrongBindingFlushForTesting) {
866   IntegerSenderConnectionPtr ptr;
867   auto binding =
868       MakeStrongBinding(std::make_unique<IntegerSenderConnectionImpl>(
869                             IntegerSenderConnectionRequest{}),
870                         MakeRequest(&ptr));
871   bool called = false;
872   IntegerSenderAssociatedPtr sender_ptr;
873   ptr->GetSender(MakeRequest(&sender_ptr));
874   sender_ptr->Echo(1, base::Bind(&SetBoolWithUnusedParameter<int>, &called));
875   EXPECT_FALSE(called);
876   // Because the flush is sent from the binding, it only guarantees that the
877   // request has been received, not the response. The second flush waits for the
878   // response to be received.
879   ASSERT_TRUE(binding);
880   binding->FlushForTesting();
881   ASSERT_TRUE(binding);
882   binding->FlushForTesting();
883   EXPECT_TRUE(called);
884 }
885 
TEST_F(AssociatedInterfaceTest,StrongBindingFlushForTestingWithClosedPeer)886 TEST_F(AssociatedInterfaceTest, StrongBindingFlushForTestingWithClosedPeer) {
887   IntegerSenderConnectionPtr ptr;
888   bool called = false;
889   auto binding =
890       MakeStrongBinding(std::make_unique<IntegerSenderConnectionImpl>(
891                             IntegerSenderConnectionRequest{}),
892                         MakeRequest(&ptr));
893   binding->set_connection_error_handler(base::Bind(&SetBool, &called));
894   ptr.reset();
895   EXPECT_FALSE(called);
896   ASSERT_TRUE(binding);
897   binding->FlushForTesting();
898   EXPECT_TRUE(called);
899   ASSERT_FALSE(binding);
900 }
901 
TEST_F(AssociatedInterfaceTest,PtrFlushForTesting)902 TEST_F(AssociatedInterfaceTest, PtrFlushForTesting) {
903   IntegerSenderConnectionPtr ptr;
904   IntegerSenderConnectionImpl impl(MakeRequest(&ptr));
905   bool called = false;
906   ptr.set_connection_error_handler(base::Bind(&Fail));
907   ptr->AsyncGetSender(base::Bind(
908       &SetBoolWithUnusedParameter<IntegerSenderAssociatedPtrInfo>, &called));
909   EXPECT_FALSE(called);
910   ptr.FlushForTesting();
911   EXPECT_TRUE(called);
912 }
913 
TEST_F(AssociatedInterfaceTest,PtrFlushForTestingWithClosedPeer)914 TEST_F(AssociatedInterfaceTest, PtrFlushForTestingWithClosedPeer) {
915   IntegerSenderConnectionPtr ptr;
916   MakeRequest(&ptr);
917   bool called = false;
918   ptr.set_connection_error_handler(base::Bind(&SetBool, &called));
919   EXPECT_FALSE(called);
920   ptr.FlushForTesting();
921   EXPECT_TRUE(called);
922   ptr.FlushForTesting();
923 }
924 
TEST_F(AssociatedInterfaceTest,AssociatedBindingConnectionErrorWithReason)925 TEST_F(AssociatedInterfaceTest, AssociatedBindingConnectionErrorWithReason) {
926   AssociatedInterfaceRequest<IntegerSender> request;
927   IntegerSenderAssociatedPtrInfo ptr_info;
928   CreateIntegerSender(&ptr_info, &request);
929 
930   IntegerSenderImpl impl(std::move(request));
931   AssociatedInterfacePtr<IntegerSender> ptr;
932   ptr.Bind(std::move(ptr_info));
933 
934   base::RunLoop run_loop;
935   impl.binding()->set_connection_error_with_reason_handler(base::Bind(
936       [](const base::Closure& quit_closure, uint32_t custom_reason,
937          const std::string& description) {
938         EXPECT_EQ(123u, custom_reason);
939         EXPECT_EQ("farewell", description);
940         quit_closure.Run();
941       },
942       run_loop.QuitClosure()));
943 
944   ptr.ResetWithReason(123u, "farewell");
945 
946   run_loop.Run();
947 }
948 
TEST_F(AssociatedInterfaceTest,PendingAssociatedBindingConnectionErrorWithReason)949 TEST_F(AssociatedInterfaceTest,
950        PendingAssociatedBindingConnectionErrorWithReason) {
951   // Test that AssociatedBinding is notified with connection error when the
952   // interface hasn't associated with a message pipe and the peer is closed.
953 
954   IntegerSenderAssociatedPtr ptr;
955   IntegerSenderImpl impl(MakeRequest(&ptr));
956 
957   base::RunLoop run_loop;
958   impl.binding()->set_connection_error_with_reason_handler(base::Bind(
959       [](const base::Closure& quit_closure, uint32_t custom_reason,
960          const std::string& description) {
961         EXPECT_EQ(123u, custom_reason);
962         EXPECT_EQ("farewell", description);
963         quit_closure.Run();
964       },
965       run_loop.QuitClosure()));
966 
967   ptr.ResetWithReason(123u, "farewell");
968 
969   run_loop.Run();
970 }
971 
TEST_F(AssociatedInterfaceTest,AssociatedPtrConnectionErrorWithReason)972 TEST_F(AssociatedInterfaceTest, AssociatedPtrConnectionErrorWithReason) {
973   AssociatedInterfaceRequest<IntegerSender> request;
974   IntegerSenderAssociatedPtrInfo ptr_info;
975   CreateIntegerSender(&ptr_info, &request);
976 
977   IntegerSenderImpl impl(std::move(request));
978   AssociatedInterfacePtr<IntegerSender> ptr;
979   ptr.Bind(std::move(ptr_info));
980 
981   base::RunLoop run_loop;
982   ptr.set_connection_error_with_reason_handler(base::Bind(
983       [](const base::Closure& quit_closure, uint32_t custom_reason,
984          const std::string& description) {
985         EXPECT_EQ(456u, custom_reason);
986         EXPECT_EQ("farewell", description);
987         quit_closure.Run();
988       },
989       run_loop.QuitClosure()));
990 
991   impl.binding()->CloseWithReason(456u, "farewell");
992 
993   run_loop.Run();
994 }
995 
TEST_F(AssociatedInterfaceTest,PendingAssociatedPtrConnectionErrorWithReason)996 TEST_F(AssociatedInterfaceTest, PendingAssociatedPtrConnectionErrorWithReason) {
997   // Test that AssociatedInterfacePtr is notified with connection error when the
998   // interface hasn't associated with a message pipe and the peer is closed.
999 
1000   IntegerSenderAssociatedPtr ptr;
1001   auto request = MakeRequest(&ptr);
1002 
1003   base::RunLoop run_loop;
1004   ptr.set_connection_error_with_reason_handler(base::Bind(
1005       [](const base::Closure& quit_closure, uint32_t custom_reason,
1006          const std::string& description) {
1007         EXPECT_EQ(456u, custom_reason);
1008         EXPECT_EQ("farewell", description);
1009         quit_closure.Run();
1010       },
1011       run_loop.QuitClosure()));
1012 
1013   request.ResetWithReason(456u, "farewell");
1014 
1015   run_loop.Run();
1016 }
1017 
TEST_F(AssociatedInterfaceTest,AssociatedRequestResetWithReason)1018 TEST_F(AssociatedInterfaceTest, AssociatedRequestResetWithReason) {
1019   AssociatedInterfaceRequest<IntegerSender> request;
1020   IntegerSenderAssociatedPtrInfo ptr_info;
1021   CreateIntegerSender(&ptr_info, &request);
1022 
1023   AssociatedInterfacePtr<IntegerSender> ptr;
1024   ptr.Bind(std::move(ptr_info));
1025 
1026   base::RunLoop run_loop;
1027   ptr.set_connection_error_with_reason_handler(base::Bind(
1028       [](const base::Closure& quit_closure, uint32_t custom_reason,
1029          const std::string& description) {
1030         EXPECT_EQ(789u, custom_reason);
1031         EXPECT_EQ("long time no see", description);
1032         quit_closure.Run();
1033       },
1034       run_loop.QuitClosure()));
1035 
1036   request.ResetWithReason(789u, "long time no see");
1037 
1038   run_loop.Run();
1039 }
1040 
TEST_F(AssociatedInterfaceTest,ThreadSafeAssociatedInterfacePtr)1041 TEST_F(AssociatedInterfaceTest, ThreadSafeAssociatedInterfacePtr) {
1042   IntegerSenderConnectionPtr connection_ptr;
1043   IntegerSenderConnectionImpl connection(MakeRequest(&connection_ptr));
1044 
1045   IntegerSenderAssociatedPtr sender;
1046   connection_ptr->GetSender(MakeRequest(&sender));
1047 
1048   scoped_refptr<ThreadSafeIntegerSenderAssociatedPtr> thread_safe_sender =
1049       ThreadSafeIntegerSenderAssociatedPtr::Create(std::move(sender));
1050 
1051   {
1052     // Test the thread safe pointer can be used from the interface ptr thread.
1053     int32_t echoed_value = 0;
1054     base::RunLoop run_loop;
1055     (*thread_safe_sender)
1056         ->Echo(123, base::Bind(&CaptureInt32, &echoed_value,
1057                                run_loop.QuitClosure()));
1058     run_loop.Run();
1059     EXPECT_EQ(123, echoed_value);
1060   }
1061 
1062   // Test the thread safe pointer can be used from another thread.
1063   base::RunLoop run_loop;
1064 
1065   auto run_method = base::Bind(
1066       [](const scoped_refptr<base::TaskRunner>& main_task_runner,
1067          const base::Closure& quit_closure,
1068          const scoped_refptr<ThreadSafeIntegerSenderAssociatedPtr>&
1069              thread_safe_sender) {
1070         auto done_callback = base::Bind(
1071             [](const scoped_refptr<base::TaskRunner>& main_task_runner,
1072                const base::Closure& quit_closure,
1073                scoped_refptr<base::SequencedTaskRunner> sender_sequence_runner,
1074                int32_t result) {
1075               EXPECT_EQ(123, result);
1076               // Validate the callback is invoked on the calling sequence.
1077               EXPECT_TRUE(sender_sequence_runner->RunsTasksInCurrentSequence());
1078               // Notify the run_loop to quit.
1079               main_task_runner->PostTask(FROM_HERE, quit_closure);
1080             });
1081         scoped_refptr<base::SequencedTaskRunner> current_sequence_runner =
1082             base::SequencedTaskRunnerHandle::Get();
1083         (*thread_safe_sender)
1084             ->Echo(123, base::Bind(done_callback, main_task_runner,
1085                                    quit_closure, current_sequence_runner));
1086       },
1087       base::SequencedTaskRunnerHandle::Get(), run_loop.QuitClosure(),
1088       thread_safe_sender);
1089   base::CreateSequencedTaskRunnerWithTraits({})->PostTask(FROM_HERE,
1090                                                           run_method);
1091 
1092   // Block until the method callback is called on the background thread.
1093   run_loop.Run();
1094 }
1095 
1096 struct ForwarderTestContext {
1097   IntegerSenderConnectionPtr connection_ptr;
1098   std::unique_ptr<IntegerSenderConnectionImpl> interface_impl;
1099   IntegerSenderAssociatedRequest sender_request;
1100 };
1101 
TEST_F(AssociatedInterfaceTest,ThreadSafeAssociatedInterfacePtrWithTaskRunner)1102 TEST_F(AssociatedInterfaceTest,
1103        ThreadSafeAssociatedInterfacePtrWithTaskRunner) {
1104   const scoped_refptr<base::SequencedTaskRunner> other_thread_task_runner =
1105       base::CreateSequencedTaskRunnerWithTraits({});
1106 
1107   ForwarderTestContext* context = new ForwarderTestContext();
1108   IntegerSenderAssociatedPtrInfo sender_info;
1109   base::WaitableEvent sender_info_bound_event(
1110       base::WaitableEvent::ResetPolicy::MANUAL,
1111       base::WaitableEvent::InitialState::NOT_SIGNALED);
1112   auto setup = [](base::WaitableEvent* sender_info_bound_event,
1113                   IntegerSenderAssociatedPtrInfo* sender_info,
1114                   ForwarderTestContext* context) {
1115     context->interface_impl = std::make_unique<IntegerSenderConnectionImpl>(
1116         MakeRequest(&context->connection_ptr));
1117 
1118     auto sender_request = MakeRequest(sender_info);
1119     context->connection_ptr->GetSender(std::move(sender_request));
1120 
1121     // Unblock the main thread as soon as |sender_info| is set.
1122     sender_info_bound_event->Signal();
1123   };
1124   other_thread_task_runner->PostTask(
1125       FROM_HERE,
1126       base::Bind(setup, &sender_info_bound_event, &sender_info, context));
1127   sender_info_bound_event.Wait();
1128 
1129   // Create a ThreadSafeAssociatedPtr that binds on the background thread and is
1130   // associated with |connection_ptr| there.
1131   scoped_refptr<ThreadSafeIntegerSenderAssociatedPtr> thread_safe_ptr =
1132       ThreadSafeIntegerSenderAssociatedPtr::Create(std::move(sender_info),
1133                                                    other_thread_task_runner);
1134 
1135   // Issue a call on the thread-safe ptr immediately. Note that this may happen
1136   // before the interface is bound on the background thread, and that must be
1137   // OK.
1138   {
1139     auto echo_callback =
1140         base::Bind([](const base::Closure& quit_closure, int32_t result) {
1141           EXPECT_EQ(123, result);
1142           quit_closure.Run();
1143         });
1144     base::RunLoop run_loop;
1145     (*thread_safe_ptr)
1146         ->Echo(123, base::Bind(echo_callback, run_loop.QuitClosure()));
1147 
1148     // Block until the method callback is called.
1149     run_loop.Run();
1150   }
1151 
1152   other_thread_task_runner->DeleteSoon(FROM_HERE, context);
1153 
1154   // Reset the pointer now so the InterfacePtr associated resources can be
1155   // deleted before the background thread's message loop is invalidated.
1156   thread_safe_ptr = nullptr;
1157 }
1158 
1159 class DiscardingAssociatedPingProviderProvider
1160     : public AssociatedPingProviderProvider {
1161  public:
GetPingProvider(AssociatedPingProviderAssociatedRequest request)1162   void GetPingProvider(
1163       AssociatedPingProviderAssociatedRequest request) override {}
1164 };
1165 
TEST_F(AssociatedInterfaceTest,CloseWithoutBindingAssociatedRequest)1166 TEST_F(AssociatedInterfaceTest, CloseWithoutBindingAssociatedRequest) {
1167   DiscardingAssociatedPingProviderProvider ping_provider_provider;
1168   mojo::Binding<AssociatedPingProviderProvider> binding(
1169       &ping_provider_provider);
1170   AssociatedPingProviderProviderPtr provider_provider;
1171   binding.Bind(mojo::MakeRequest(&provider_provider));
1172   AssociatedPingProviderAssociatedPtr provider;
1173   provider_provider->GetPingProvider(mojo::MakeRequest(&provider));
1174   PingServiceAssociatedPtr ping;
1175   provider->GetPing(mojo::MakeRequest(&ping));
1176   base::RunLoop run_loop;
1177   ping.set_connection_error_handler(run_loop.QuitClosure());
1178   run_loop.Run();
1179 }
1180 
TEST_F(AssociatedInterfaceTest,AssociateWithDisconnectedPipe)1181 TEST_F(AssociatedInterfaceTest, AssociateWithDisconnectedPipe) {
1182   IntegerSenderAssociatedPtr sender;
1183   AssociateWithDisconnectedPipe(MakeRequest(&sender).PassHandle());
1184   sender->Send(42);
1185 }
1186 
1187 }  // namespace
1188 }  // namespace test
1189 }  // namespace mojo
1190