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