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