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 // Note: This file tests both binding.h (mojo::Binding) and strong_binding.h
6 // (mojo::StrongBinding).
7
8 #include "mojo/public/cpp/bindings/binding.h"
9
10 #include <stdint.h>
11 #include <utility>
12
13 #include "base/macros.h"
14 #include "base/memory/ptr_util.h"
15 #include "base/memory/weak_ptr.h"
16 #include "base/run_loop.h"
17 #include "mojo/core/embedder/embedder.h"
18 #include "mojo/public/cpp/bindings/strong_binding.h"
19 #include "mojo/public/cpp/bindings/tests/bindings_test_base.h"
20 #include "mojo/public/interfaces/bindings/tests/ping_service.mojom.h"
21 #include "mojo/public/interfaces/bindings/tests/sample_interfaces.mojom.h"
22 #include "mojo/public/interfaces/bindings/tests/sample_service.mojom.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24
25 namespace mojo {
26 namespace {
27
28 class ServiceImpl : public sample::Service {
29 public:
ServiceImpl(bool * was_deleted=nullptr)30 explicit ServiceImpl(bool* was_deleted = nullptr)
31 : was_deleted_(was_deleted) {}
~ServiceImpl()32 ~ServiceImpl() override {
33 if (was_deleted_)
34 *was_deleted_ = true;
35 }
36
37 private:
38 // sample::Service implementation
Frobinate(sample::FooPtr foo,BazOptions options,sample::PortPtr port,const FrobinateCallback & callback)39 void Frobinate(sample::FooPtr foo,
40 BazOptions options,
41 sample::PortPtr port,
42 const FrobinateCallback& callback) override {
43 callback.Run(1);
44 }
GetPort(InterfaceRequest<sample::Port> port)45 void GetPort(InterfaceRequest<sample::Port> port) override {}
46
47 bool* const was_deleted_;
48
49 DISALLOW_COPY_AND_ASSIGN(ServiceImpl);
50 };
51
52 template <typename... Args>
DoSetFlagAndRunClosure(bool * flag,const base::Closure & closure,Args...args)53 void DoSetFlagAndRunClosure(bool* flag,
54 const base::Closure& closure,
55 Args... args) {
56 *flag = true;
57 if (!closure.is_null())
58 closure.Run();
59 }
60
61 template <typename... Args>
SetFlagAndRunClosure(bool * flag,const base::Closure & callback=base::Closure ())62 base::Callback<void(Args...)> SetFlagAndRunClosure(
63 bool* flag,
64 const base::Closure& callback = base::Closure()) {
65 return base::Bind(&DoSetFlagAndRunClosure<Args...>, flag, callback);
66 }
67
68 // BindingTest -----------------------------------------------------------------
69
70 using BindingTest = BindingsTestBase;
71
TEST_P(BindingTest,Close)72 TEST_P(BindingTest, Close) {
73 bool called = false;
74 sample::ServicePtr ptr;
75 auto request = MakeRequest(&ptr);
76 base::RunLoop run_loop;
77 ptr.set_connection_error_handler(
78 SetFlagAndRunClosure(&called, run_loop.QuitClosure()));
79 ServiceImpl impl;
80 Binding<sample::Service> binding(&impl, std::move(request));
81
82 binding.Close();
83 EXPECT_FALSE(called);
84 run_loop.Run();
85 EXPECT_TRUE(called);
86 }
87
88 // Tests that destroying a mojo::Binding closes the bound message pipe handle.
TEST_P(BindingTest,DestroyClosesMessagePipe)89 TEST_P(BindingTest, DestroyClosesMessagePipe) {
90 bool encountered_error = false;
91 ServiceImpl impl;
92 sample::ServicePtr ptr;
93 auto request = MakeRequest(&ptr);
94 base::RunLoop run_loop;
95 ptr.set_connection_error_handler(
96 SetFlagAndRunClosure(&encountered_error, run_loop.QuitClosure()));
97 bool called = false;
98 base::RunLoop run_loop2;
99 {
100 Binding<sample::Service> binding(&impl, std::move(request));
101 ptr->Frobinate(nullptr, sample::Service::BazOptions::REGULAR, nullptr,
102 SetFlagAndRunClosure<int32_t>(&called,
103 run_loop2.QuitClosure()));
104 run_loop2.Run();
105 EXPECT_TRUE(called);
106 EXPECT_FALSE(encountered_error);
107 }
108 // Now that the Binding is out of scope we should detect an error on the other
109 // end of the pipe.
110 run_loop.Run();
111 EXPECT_TRUE(encountered_error);
112
113 // And calls should fail.
114 called = false;
115 ptr->Frobinate(nullptr, sample::Service::BazOptions::REGULAR, nullptr,
116 SetFlagAndRunClosure<int32_t>(&called,
117 run_loop2.QuitClosure()));
118 base::RunLoop().RunUntilIdle();
119 EXPECT_FALSE(called);
120 }
121
122 // Tests that the binding's connection error handler gets called when the other
123 // end is closed.
TEST_P(BindingTest,ConnectionError)124 TEST_P(BindingTest, ConnectionError) {
125 bool called = false;
126 {
127 ServiceImpl impl;
128 sample::ServicePtr ptr;
129 Binding<sample::Service> binding(&impl, MakeRequest(&ptr));
130 base::RunLoop run_loop;
131 binding.set_connection_error_handler(
132 SetFlagAndRunClosure(&called, run_loop.QuitClosure()));
133 ptr.reset();
134 EXPECT_FALSE(called);
135 run_loop.Run();
136 EXPECT_TRUE(called);
137 // We want to make sure that it isn't called again during destruction.
138 called = false;
139 }
140 EXPECT_FALSE(called);
141 }
142
143 // Tests that calling Close doesn't result in the connection error handler being
144 // called.
TEST_P(BindingTest,CloseDoesntCallConnectionErrorHandler)145 TEST_P(BindingTest, CloseDoesntCallConnectionErrorHandler) {
146 ServiceImpl impl;
147 sample::ServicePtr ptr;
148 Binding<sample::Service> binding(&impl, MakeRequest(&ptr));
149 bool called = false;
150 binding.set_connection_error_handler(SetFlagAndRunClosure(&called));
151 binding.Close();
152 base::RunLoop().RunUntilIdle();
153 EXPECT_FALSE(called);
154
155 // We can also close the other end, and the error handler still won't be
156 // called.
157 ptr.reset();
158 base::RunLoop().RunUntilIdle();
159 EXPECT_FALSE(called);
160 }
161
162 class ServiceImplWithBinding : public ServiceImpl {
163 public:
ServiceImplWithBinding(bool * was_deleted,const base::Closure & closure,InterfaceRequest<sample::Service> request)164 ServiceImplWithBinding(bool* was_deleted,
165 const base::Closure& closure,
166 InterfaceRequest<sample::Service> request)
167 : ServiceImpl(was_deleted),
168 binding_(this, std::move(request)),
169 closure_(closure) {
170 binding_.set_connection_error_handler(
171 base::Bind(&ServiceImplWithBinding::OnConnectionError,
172 base::Unretained(this)));
173 }
174
175 private:
~ServiceImplWithBinding()176 ~ServiceImplWithBinding() override{
177 closure_.Run();
178 }
179
OnConnectionError()180 void OnConnectionError() { delete this; }
181
182 Binding<sample::Service> binding_;
183 base::Closure closure_;
184
185 DISALLOW_COPY_AND_ASSIGN(ServiceImplWithBinding);
186 };
187
188 // Tests that the binding may be deleted in the connection error handler.
TEST_P(BindingTest,SelfDeleteOnConnectionError)189 TEST_P(BindingTest, SelfDeleteOnConnectionError) {
190 bool was_deleted = false;
191 sample::ServicePtr ptr;
192 // This should delete itself on connection error.
193 base::RunLoop run_loop;
194 new ServiceImplWithBinding(&was_deleted, run_loop.QuitClosure(),
195 MakeRequest(&ptr));
196 ptr.reset();
197 EXPECT_FALSE(was_deleted);
198 run_loop.Run();
199 EXPECT_TRUE(was_deleted);
200 }
201
202 // Tests that explicitly calling Unbind followed by rebinding works.
TEST_P(BindingTest,Unbind)203 TEST_P(BindingTest, Unbind) {
204 ServiceImpl impl;
205 sample::ServicePtr ptr;
206 Binding<sample::Service> binding(&impl, MakeRequest(&ptr));
207
208 bool called = false;
209 base::RunLoop run_loop;
210 ptr->Frobinate(nullptr, sample::Service::BazOptions::REGULAR, nullptr,
211 SetFlagAndRunClosure<int32_t>(&called,
212 run_loop.QuitClosure()));
213 run_loop.Run();
214 EXPECT_TRUE(called);
215
216 called = false;
217 auto request = binding.Unbind();
218 EXPECT_FALSE(binding.is_bound());
219 // All calls should fail when not bound...
220 ptr->Frobinate(nullptr, sample::Service::BazOptions::REGULAR, nullptr,
221 SetFlagAndRunClosure<int32_t>(&called,
222 run_loop.QuitClosure()));
223 base::RunLoop().RunUntilIdle();
224 EXPECT_FALSE(called);
225
226 called = false;
227 binding.Bind(std::move(request));
228 EXPECT_TRUE(binding.is_bound());
229 // ...and should succeed again when the rebound.
230 base::RunLoop run_loop2;
231 ptr->Frobinate(nullptr, sample::Service::BazOptions::REGULAR, nullptr,
232 SetFlagAndRunClosure<int32_t>(&called,
233 run_loop2.QuitClosure()));
234 run_loop2.Run();
235 EXPECT_TRUE(called);
236 }
237
238 class IntegerAccessorImpl : public sample::IntegerAccessor {
239 public:
IntegerAccessorImpl()240 IntegerAccessorImpl() {}
~IntegerAccessorImpl()241 ~IntegerAccessorImpl() override {}
242
243 private:
244 // sample::IntegerAccessor implementation.
GetInteger(const GetIntegerCallback & callback)245 void GetInteger(const GetIntegerCallback& callback) override {
246 callback.Run(1, sample::Enum::VALUE);
247 }
SetInteger(int64_t data,sample::Enum type)248 void SetInteger(int64_t data, sample::Enum type) override {}
249
250 DISALLOW_COPY_AND_ASSIGN(IntegerAccessorImpl);
251 };
252
TEST_P(BindingTest,PauseResume)253 TEST_P(BindingTest, PauseResume) {
254 bool called = false;
255 base::RunLoop run_loop;
256 sample::ServicePtr ptr;
257 auto request = MakeRequest(&ptr);
258 ServiceImpl impl;
259 Binding<sample::Service> binding(&impl, std::move(request));
260 binding.PauseIncomingMethodCallProcessing();
261 ptr->Frobinate(nullptr, sample::Service::BazOptions::REGULAR, nullptr,
262 SetFlagAndRunClosure<int32_t>(&called,
263 run_loop.QuitClosure()));
264 EXPECT_FALSE(called);
265 base::RunLoop().RunUntilIdle();
266 // Frobinate() should not be called as the binding is paused.
267 EXPECT_FALSE(called);
268
269 // Resume the binding, which should trigger processing.
270 binding.ResumeIncomingMethodCallProcessing();
271 run_loop.Run();
272 EXPECT_TRUE(called);
273 }
274
275 // Verifies the connection error handler is not run while a binding is paused.
TEST_P(BindingTest,ErrorHandleNotRunWhilePaused)276 TEST_P(BindingTest, ErrorHandleNotRunWhilePaused) {
277 bool called = false;
278 base::RunLoop run_loop;
279 sample::ServicePtr ptr;
280 auto request = MakeRequest(&ptr);
281 ServiceImpl impl;
282 Binding<sample::Service> binding(&impl, std::move(request));
283 binding.set_connection_error_handler(
284 SetFlagAndRunClosure(&called, run_loop.QuitClosure()));
285 binding.PauseIncomingMethodCallProcessing();
286
287 ptr.reset();
288 base::RunLoop().RunUntilIdle();
289 // The connection error handle should not be called as the binding is paused.
290 EXPECT_FALSE(called);
291
292 // Resume the binding, which should trigger the error handler.
293 binding.ResumeIncomingMethodCallProcessing();
294 run_loop.Run();
295 EXPECT_TRUE(called);
296 }
297
298 class PingServiceImpl : public test::PingService {
299 public:
PingServiceImpl()300 PingServiceImpl() {}
~PingServiceImpl()301 ~PingServiceImpl() override {}
302
303 // test::PingService:
Ping(const PingCallback & callback)304 void Ping(const PingCallback& callback) override {
305 if (!ping_handler_.is_null())
306 ping_handler_.Run();
307 callback.Run();
308 }
309
set_ping_handler(const base::Closure & handler)310 void set_ping_handler(const base::Closure& handler) {
311 ping_handler_ = handler;
312 }
313
314 private:
315 base::Closure ping_handler_;
316
317 DISALLOW_COPY_AND_ASSIGN(PingServiceImpl);
318 };
319
320 class CallbackFilter : public MessageReceiver {
321 public:
CallbackFilter(const base::Closure & callback)322 explicit CallbackFilter(const base::Closure& callback)
323 : callback_(callback) {}
~CallbackFilter()324 ~CallbackFilter() override {}
325
Wrap(const base::Closure & callback)326 static std::unique_ptr<CallbackFilter> Wrap(const base::Closure& callback) {
327 return std::make_unique<CallbackFilter>(callback);
328 }
329
330 // MessageReceiver:
Accept(Message * message)331 bool Accept(Message* message) override {
332 callback_.Run();
333 return true;
334 }
335
336 private:
337 const base::Closure callback_;
338 };
339
340 // Verifies that message filters are notified in the order they were added and
341 // are always notified before a message is dispatched.
TEST_P(BindingTest,MessageFilter)342 TEST_P(BindingTest, MessageFilter) {
343 test::PingServicePtr ptr;
344 PingServiceImpl impl;
345 mojo::Binding<test::PingService> binding(&impl, MakeRequest(&ptr));
346
347 int status = 0;
348 auto handler_helper = [] (int* status, int expected_status, int new_status) {
349 EXPECT_EQ(expected_status, *status);
350 *status = new_status;
351 };
352 auto create_handler = [&] (int expected_status, int new_status) {
353 return base::Bind(handler_helper, &status, expected_status, new_status);
354 };
355
356 binding.AddFilter(CallbackFilter::Wrap(create_handler(0, 1)));
357 binding.AddFilter(CallbackFilter::Wrap(create_handler(1, 2)));
358 impl.set_ping_handler(create_handler(2, 3));
359
360 for (int i = 0; i < 10; ++i) {
361 status = 0;
362 base::RunLoop loop;
363 ptr->Ping(loop.QuitClosure());
364 loop.Run();
365 EXPECT_EQ(3, status);
366 }
367 }
368
Fail()369 void Fail() {
370 FAIL() << "Unexpected connection error";
371 }
372
TEST_P(BindingTest,FlushForTesting)373 TEST_P(BindingTest, FlushForTesting) {
374 bool called = false;
375 sample::ServicePtr ptr;
376 auto request = MakeRequest(&ptr);
377 ServiceImpl impl;
378 Binding<sample::Service> binding(&impl, std::move(request));
379 binding.set_connection_error_handler(base::Bind(&Fail));
380
381 ptr->Frobinate(nullptr, sample::Service::BazOptions::REGULAR, nullptr,
382 SetFlagAndRunClosure<int32_t>(&called));
383 EXPECT_FALSE(called);
384 // Because the flush is sent from the binding, it only guarantees that the
385 // request has been received, not the response. The second flush waits for the
386 // response to be received.
387 binding.FlushForTesting();
388 binding.FlushForTesting();
389 EXPECT_TRUE(called);
390 }
391
TEST_P(BindingTest,FlushForTestingWithClosedPeer)392 TEST_P(BindingTest, FlushForTestingWithClosedPeer) {
393 bool called = false;
394 sample::ServicePtr ptr;
395 auto request = MakeRequest(&ptr);
396 ServiceImpl impl;
397 Binding<sample::Service> binding(&impl, std::move(request));
398 binding.set_connection_error_handler(SetFlagAndRunClosure(&called));
399 ptr.reset();
400
401 EXPECT_FALSE(called);
402 binding.FlushForTesting();
403 EXPECT_TRUE(called);
404 binding.FlushForTesting();
405 }
406
TEST_P(BindingTest,ConnectionErrorWithReason)407 TEST_P(BindingTest, ConnectionErrorWithReason) {
408 sample::ServicePtr ptr;
409 auto request = MakeRequest(&ptr);
410 ServiceImpl impl;
411 Binding<sample::Service> binding(&impl, std::move(request));
412
413 base::RunLoop run_loop;
414 binding.set_connection_error_with_reason_handler(base::Bind(
415 [](const base::Closure& quit_closure, uint32_t custom_reason,
416 const std::string& description) {
417 EXPECT_EQ(1234u, custom_reason);
418 EXPECT_EQ("hello", description);
419 quit_closure.Run();
420 },
421 run_loop.QuitClosure()));
422
423 ptr.ResetWithReason(1234u, "hello");
424
425 run_loop.Run();
426 }
427
428 template <typename T>
429 struct WeakPtrImplRefTraits {
430 using PointerType = base::WeakPtr<T>;
431
IsNullmojo::__anon04d1dd060111::WeakPtrImplRefTraits432 static bool IsNull(const base::WeakPtr<T>& ptr) { return !ptr; }
GetRawPointermojo::__anon04d1dd060111::WeakPtrImplRefTraits433 static T* GetRawPointer(base::WeakPtr<T>* ptr) { return ptr->get(); }
434 };
435
436 template <typename T>
437 using WeakBinding = Binding<T, WeakPtrImplRefTraits<T>>;
438
TEST_P(BindingTest,CustomImplPointerType)439 TEST_P(BindingTest, CustomImplPointerType) {
440 PingServiceImpl impl;
441 base::WeakPtrFactory<test::PingService> weak_factory(&impl);
442
443 test::PingServicePtr proxy;
444 WeakBinding<test::PingService> binding(weak_factory.GetWeakPtr(),
445 MakeRequest(&proxy));
446
447 {
448 // Ensure the binding is functioning.
449 base::RunLoop run_loop;
450 proxy->Ping(run_loop.QuitClosure());
451 run_loop.Run();
452 }
453
454 {
455 // Attempt to dispatch another message after the WeakPtr is invalidated.
456 base::Closure assert_not_reached = base::Bind([] { NOTREACHED(); });
457 impl.set_ping_handler(assert_not_reached);
458 proxy->Ping(assert_not_reached);
459
460 // The binding will close its end of the pipe which will trigger a
461 // connection error on |proxy|.
462 base::RunLoop run_loop;
463 proxy.set_connection_error_handler(run_loop.QuitClosure());
464 weak_factory.InvalidateWeakPtrs();
465 run_loop.Run();
466 }
467 }
468
TEST_P(BindingTest,ReportBadMessage)469 TEST_P(BindingTest, ReportBadMessage) {
470 bool called = false;
471 test::PingServicePtr ptr;
472 auto request = MakeRequest(&ptr);
473 base::RunLoop run_loop;
474 ptr.set_connection_error_handler(
475 SetFlagAndRunClosure(&called, run_loop.QuitClosure()));
476 PingServiceImpl impl;
477 Binding<test::PingService> binding(&impl, std::move(request));
478 impl.set_ping_handler(base::Bind(
479 [](Binding<test::PingService>* binding) {
480 binding->ReportBadMessage("received bad message");
481 },
482 &binding));
483
484 std::string received_error;
485 core::SetDefaultProcessErrorCallback(
486 base::Bind([](std::string* out_error,
487 const std::string& error) { *out_error = error; },
488 &received_error));
489
490 ptr->Ping(base::Bind([] {}));
491 EXPECT_FALSE(called);
492 run_loop.Run();
493 EXPECT_TRUE(called);
494 EXPECT_EQ("received bad message", received_error);
495
496 core::SetDefaultProcessErrorCallback(mojo::core::ProcessErrorCallback());
497 }
498
TEST_P(BindingTest,GetBadMessageCallback)499 TEST_P(BindingTest, GetBadMessageCallback) {
500 test::PingServicePtr ptr;
501 auto request = MakeRequest(&ptr);
502 base::RunLoop run_loop;
503 PingServiceImpl impl;
504 ReportBadMessageCallback bad_message_callback;
505
506 std::string received_error;
507 core::SetDefaultProcessErrorCallback(
508 base::Bind([](std::string* out_error,
509 const std::string& error) { *out_error = error; },
510 &received_error));
511
512 {
513 Binding<test::PingService> binding(&impl, std::move(request));
514 impl.set_ping_handler(base::Bind(
515 [](Binding<test::PingService>* binding,
516 ReportBadMessageCallback* out_callback) {
517 *out_callback = binding->GetBadMessageCallback();
518 },
519 &binding, &bad_message_callback));
520 ptr->Ping(run_loop.QuitClosure());
521 run_loop.Run();
522 EXPECT_TRUE(received_error.empty());
523 EXPECT_TRUE(bad_message_callback);
524 }
525
526 std::move(bad_message_callback).Run("delayed bad message");
527 EXPECT_EQ("delayed bad message", received_error);
528
529 core::SetDefaultProcessErrorCallback(mojo::core::ProcessErrorCallback());
530 }
531
532 // StrongBindingTest -----------------------------------------------------------
533
534 using StrongBindingTest = BindingsTestBase;
535
536 // Tests that destroying a mojo::StrongBinding closes the bound message pipe
537 // handle but does *not* destroy the implementation object.
TEST_P(StrongBindingTest,DestroyClosesMessagePipe)538 TEST_P(StrongBindingTest, DestroyClosesMessagePipe) {
539 base::RunLoop run_loop;
540 bool encountered_error = false;
541 bool was_deleted = false;
542 sample::ServicePtr ptr;
543 auto request = MakeRequest(&ptr);
544 ptr.set_connection_error_handler(
545 SetFlagAndRunClosure(&encountered_error, run_loop.QuitClosure()));
546 bool called = false;
547 base::RunLoop run_loop2;
548
549 auto binding = MakeStrongBinding(std::make_unique<ServiceImpl>(&was_deleted),
550 std::move(request));
551 ptr->Frobinate(
552 nullptr, sample::Service::BazOptions::REGULAR, nullptr,
553 SetFlagAndRunClosure<int32_t>(&called, run_loop2.QuitClosure()));
554 run_loop2.Run();
555 EXPECT_TRUE(called);
556 EXPECT_FALSE(encountered_error);
557 binding->Close();
558
559 // Now that the StrongBinding is closed we should detect an error on the other
560 // end of the pipe.
561 run_loop.Run();
562 EXPECT_TRUE(encountered_error);
563
564 // Destroying the StrongBinding also destroys the impl.
565 ASSERT_TRUE(was_deleted);
566 }
567
568 // Tests the typical case, where the implementation object owns the
569 // StrongBinding (and should be destroyed on connection error).
TEST_P(StrongBindingTest,ConnectionErrorDestroysImpl)570 TEST_P(StrongBindingTest, ConnectionErrorDestroysImpl) {
571 sample::ServicePtr ptr;
572 bool was_deleted = false;
573 // Will delete itself.
574 base::RunLoop run_loop;
575 new ServiceImplWithBinding(&was_deleted, run_loop.QuitClosure(),
576 MakeRequest(&ptr));
577
578 base::RunLoop().RunUntilIdle();
579 EXPECT_FALSE(was_deleted);
580
581 ptr.reset();
582 EXPECT_FALSE(was_deleted);
583 run_loop.Run();
584 EXPECT_TRUE(was_deleted);
585 }
586
TEST_P(StrongBindingTest,FlushForTesting)587 TEST_P(StrongBindingTest, FlushForTesting) {
588 bool called = false;
589 bool was_deleted = false;
590 sample::ServicePtr ptr;
591 auto request = MakeRequest(&ptr);
592 auto binding = MakeStrongBinding(std::make_unique<ServiceImpl>(&was_deleted),
593 std::move(request));
594 binding->set_connection_error_handler(base::Bind(&Fail));
595
596 ptr->Frobinate(nullptr, sample::Service::BazOptions::REGULAR, nullptr,
597 SetFlagAndRunClosure<int32_t>(&called));
598 EXPECT_FALSE(called);
599 // Because the flush is sent from the binding, it only guarantees that the
600 // request has been received, not the response. The second flush waits for the
601 // response to be received.
602 ASSERT_TRUE(binding);
603 binding->FlushForTesting();
604 ASSERT_TRUE(binding);
605 binding->FlushForTesting();
606 EXPECT_TRUE(called);
607 EXPECT_FALSE(was_deleted);
608 ptr.reset();
609 ASSERT_TRUE(binding);
610 binding->set_connection_error_handler(base::Closure());
611 binding->FlushForTesting();
612 EXPECT_TRUE(was_deleted);
613 }
614
TEST_P(StrongBindingTest,FlushForTestingWithClosedPeer)615 TEST_P(StrongBindingTest, FlushForTestingWithClosedPeer) {
616 bool called = false;
617 bool was_deleted = false;
618 sample::ServicePtr ptr;
619 auto request = MakeRequest(&ptr);
620 auto binding = MakeStrongBinding(std::make_unique<ServiceImpl>(&was_deleted),
621 std::move(request));
622 binding->set_connection_error_handler(SetFlagAndRunClosure(&called));
623 ptr.reset();
624
625 EXPECT_FALSE(called);
626 EXPECT_FALSE(was_deleted);
627 ASSERT_TRUE(binding);
628 binding->FlushForTesting();
629 EXPECT_TRUE(called);
630 EXPECT_TRUE(was_deleted);
631 ASSERT_FALSE(binding);
632 }
633
TEST_P(StrongBindingTest,ConnectionErrorWithReason)634 TEST_P(StrongBindingTest, ConnectionErrorWithReason) {
635 sample::ServicePtr ptr;
636 auto request = MakeRequest(&ptr);
637 auto binding =
638 MakeStrongBinding(std::make_unique<ServiceImpl>(), std::move(request));
639 base::RunLoop run_loop;
640 binding->set_connection_error_with_reason_handler(base::Bind(
641 [](const base::Closure& quit_closure, uint32_t custom_reason,
642 const std::string& description) {
643 EXPECT_EQ(5678u, custom_reason);
644 EXPECT_EQ("hello", description);
645 quit_closure.Run();
646 },
647 run_loop.QuitClosure()));
648
649 ptr.ResetWithReason(5678u, "hello");
650
651 run_loop.Run();
652 }
653
654 INSTANTIATE_MOJO_BINDINGS_TEST_CASE_P(BindingTest);
655 INSTANTIATE_MOJO_BINDINGS_TEST_CASE_P(StrongBindingTest);
656
657 } // namespace
658 } // mojo
659