• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 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 <memory>
6 #include <utility>
7 
8 #include "base/run_loop.h"
9 #include "mojo/core/embedder/embedder.h"
10 #include "mojo/public/cpp/bindings/associated_binding_set.h"
11 #include "mojo/public/cpp/bindings/binding_set.h"
12 #include "mojo/public/cpp/bindings/strong_binding_set.h"
13 #include "mojo/public/cpp/bindings/tests/bindings_test_base.h"
14 #include "mojo/public/interfaces/bindings/tests/ping_service.mojom.h"
15 #include "mojo/public/interfaces/bindings/tests/test_associated_interfaces.mojom.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 
18 namespace mojo {
19 namespace test {
20 namespace {
21 
22 using BindingSetTest = BindingsTestBase;
23 
24 template <typename BindingSetType, typename ContextType>
ExpectContextHelper(BindingSetType * binding_set,ContextType expected_context)25 void ExpectContextHelper(BindingSetType* binding_set,
26                          ContextType expected_context) {
27   EXPECT_EQ(expected_context, binding_set->dispatch_context());
28 }
29 
30 template <typename BindingSetType, typename ContextType>
ExpectContext(BindingSetType * binding_set,ContextType expected_context)31 base::Closure ExpectContext(BindingSetType* binding_set,
32                             ContextType expected_context) {
33   return base::Bind(
34       &ExpectContextHelper<BindingSetType, ContextType>, binding_set,
35       expected_context);
36 }
37 
38 template <typename BindingSetType>
ExpectBindingIdHelper(BindingSetType * binding_set,BindingId expected_binding_id)39 void ExpectBindingIdHelper(BindingSetType* binding_set,
40                            BindingId expected_binding_id) {
41   EXPECT_EQ(expected_binding_id, binding_set->dispatch_binding());
42 }
43 
44 template <typename BindingSetType>
ExpectBindingId(BindingSetType * binding_set,BindingId expected_binding_id)45 base::Closure ExpectBindingId(BindingSetType* binding_set,
46                               BindingId expected_binding_id) {
47   return base::Bind(&ExpectBindingIdHelper<BindingSetType>, binding_set,
48                     expected_binding_id);
49 }
50 
51 template <typename BindingSetType>
ReportBadMessageHelper(BindingSetType * binding_set,const std::string & error)52 void ReportBadMessageHelper(BindingSetType* binding_set,
53                             const std::string& error) {
54   binding_set->ReportBadMessage(error);
55 }
56 
57 template <typename BindingSetType>
ReportBadMessage(BindingSetType * binding_set,const std::string & error)58 base::Closure ReportBadMessage(BindingSetType* binding_set,
59                                const std::string& error) {
60   return base::Bind(&ReportBadMessageHelper<BindingSetType>, binding_set,
61                     error);
62 }
63 
64 template <typename BindingSetType>
SaveBadMessageCallbackHelper(BindingSetType * binding_set,ReportBadMessageCallback * callback)65 void SaveBadMessageCallbackHelper(BindingSetType* binding_set,
66                                   ReportBadMessageCallback* callback) {
67   *callback = binding_set->GetBadMessageCallback();
68 }
69 
70 template <typename BindingSetType>
SaveBadMessageCallback(BindingSetType * binding_set,ReportBadMessageCallback * callback)71 base::Closure SaveBadMessageCallback(BindingSetType* binding_set,
72                                      ReportBadMessageCallback* callback) {
73   return base::Bind(&SaveBadMessageCallbackHelper<BindingSetType>, binding_set,
74                     callback);
75 }
76 
Sequence(const base::Closure & first,const base::Closure & second)77 base::Closure Sequence(const base::Closure& first,
78                        const base::Closure& second) {
79   return base::Bind(
80       [] (const base::Closure& first, const base::Closure& second) {
81         first.Run();
82         second.Run();
83       }, first, second);
84 }
85 
86 class PingImpl : public PingService {
87  public:
PingImpl()88   PingImpl() {}
~PingImpl()89   ~PingImpl() override {}
90 
set_ping_handler(const base::Closure & handler)91   void set_ping_handler(const base::Closure& handler) {
92     ping_handler_ = handler;
93   }
94 
95  private:
96   // PingService:
Ping(const PingCallback & callback)97   void Ping(const PingCallback& callback) override {
98     if (!ping_handler_.is_null())
99       ping_handler_.Run();
100     callback.Run();
101   }
102 
103   base::Closure ping_handler_;
104 };
105 
TEST_P(BindingSetTest,BindingSetContext)106 TEST_P(BindingSetTest, BindingSetContext) {
107   PingImpl impl;
108 
109   BindingSet<PingService, int> bindings;
110   PingServicePtr ping_a, ping_b;
111   bindings.AddBinding(&impl, MakeRequest(&ping_a), 1);
112   bindings.AddBinding(&impl, MakeRequest(&ping_b), 2);
113 
114   {
115     impl.set_ping_handler(ExpectContext(&bindings, 1));
116     base::RunLoop loop;
117     ping_a->Ping(loop.QuitClosure());
118     loop.Run();
119   }
120 
121   {
122     impl.set_ping_handler(ExpectContext(&bindings, 2));
123     base::RunLoop loop;
124     ping_b->Ping(loop.QuitClosure());
125     loop.Run();
126   }
127 
128   {
129     base::RunLoop loop;
130     bindings.set_connection_error_handler(
131         Sequence(ExpectContext(&bindings, 1), loop.QuitClosure()));
132     ping_a.reset();
133     loop.Run();
134   }
135 
136   {
137     base::RunLoop loop;
138     bindings.set_connection_error_handler(
139         Sequence(ExpectContext(&bindings, 2), loop.QuitClosure()));
140     ping_b.reset();
141     loop.Run();
142   }
143 
144   EXPECT_TRUE(bindings.empty());
145 }
146 
TEST_P(BindingSetTest,BindingSetDispatchBinding)147 TEST_P(BindingSetTest, BindingSetDispatchBinding) {
148   PingImpl impl;
149 
150   BindingSet<PingService, int> bindings;
151   PingServicePtr ping_a, ping_b;
152   BindingId id_a = bindings.AddBinding(&impl, MakeRequest(&ping_a), 1);
153   BindingId id_b = bindings.AddBinding(&impl, MakeRequest(&ping_b), 2);
154 
155   {
156     impl.set_ping_handler(ExpectBindingId(&bindings, id_a));
157     base::RunLoop loop;
158     ping_a->Ping(loop.QuitClosure());
159     loop.Run();
160   }
161 
162   {
163     impl.set_ping_handler(ExpectBindingId(&bindings, id_b));
164     base::RunLoop loop;
165     ping_b->Ping(loop.QuitClosure());
166     loop.Run();
167   }
168 
169   {
170     base::RunLoop loop;
171     bindings.set_connection_error_handler(
172         Sequence(ExpectBindingId(&bindings, id_a), loop.QuitClosure()));
173     ping_a.reset();
174     loop.Run();
175   }
176 
177   {
178     base::RunLoop loop;
179     bindings.set_connection_error_handler(
180         Sequence(ExpectBindingId(&bindings, id_b), loop.QuitClosure()));
181     ping_b.reset();
182     loop.Run();
183   }
184 
185   EXPECT_TRUE(bindings.empty());
186 }
187 
TEST_P(BindingSetTest,BindingSetConnectionErrorWithReason)188 TEST_P(BindingSetTest, BindingSetConnectionErrorWithReason) {
189   PingImpl impl;
190   PingServicePtr ptr;
191   BindingSet<PingService> bindings;
192   bindings.AddBinding(&impl, MakeRequest(&ptr));
193 
194   base::RunLoop run_loop;
195   bindings.set_connection_error_with_reason_handler(base::Bind(
196       [](const base::Closure& quit_closure, uint32_t custom_reason,
197          const std::string& description) {
198         EXPECT_EQ(1024u, custom_reason);
199         EXPECT_EQ("bye", description);
200         quit_closure.Run();
201       },
202       run_loop.QuitClosure()));
203 
204   ptr.ResetWithReason(1024u, "bye");
205 }
206 
TEST_P(BindingSetTest,BindingSetReportBadMessage)207 TEST_P(BindingSetTest, BindingSetReportBadMessage) {
208   PingImpl impl;
209 
210   std::string last_received_error;
211   core::SetDefaultProcessErrorCallback(
212       base::Bind([](std::string* out_error,
213                     const std::string& error) { *out_error = error; },
214                  &last_received_error));
215 
216   BindingSet<PingService, int> bindings;
217   PingServicePtr ping_a, ping_b;
218   bindings.AddBinding(&impl, MakeRequest(&ping_a), 1);
219   bindings.AddBinding(&impl, MakeRequest(&ping_b), 2);
220 
221   {
222     impl.set_ping_handler(ReportBadMessage(&bindings, "message 1"));
223     base::RunLoop loop;
224     ping_a.set_connection_error_handler(loop.QuitClosure());
225     ping_a->Ping(base::Bind([] {}));
226     loop.Run();
227     EXPECT_EQ("message 1", last_received_error);
228   }
229 
230   {
231     impl.set_ping_handler(ReportBadMessage(&bindings, "message 2"));
232     base::RunLoop loop;
233     ping_b.set_connection_error_handler(loop.QuitClosure());
234     ping_b->Ping(base::Bind([] {}));
235     loop.Run();
236     EXPECT_EQ("message 2", last_received_error);
237   }
238 
239   EXPECT_TRUE(bindings.empty());
240 
241   core::SetDefaultProcessErrorCallback(mojo::core::ProcessErrorCallback());
242 }
243 
TEST_P(BindingSetTest,BindingSetGetBadMessageCallback)244 TEST_P(BindingSetTest, BindingSetGetBadMessageCallback) {
245   PingImpl impl;
246 
247   std::string last_received_error;
248   core::SetDefaultProcessErrorCallback(
249       base::Bind([](std::string* out_error,
250                     const std::string& error) { *out_error = error; },
251                  &last_received_error));
252 
253   BindingSet<PingService, int> bindings;
254   PingServicePtr ping_a, ping_b;
255   bindings.AddBinding(&impl, MakeRequest(&ping_a), 1);
256   bindings.AddBinding(&impl, MakeRequest(&ping_b), 2);
257 
258   ReportBadMessageCallback bad_message_callback_a;
259   ReportBadMessageCallback bad_message_callback_b;
260 
261   {
262     impl.set_ping_handler(
263         SaveBadMessageCallback(&bindings, &bad_message_callback_a));
264     base::RunLoop loop;
265     ping_a->Ping(loop.QuitClosure());
266     loop.Run();
267     ping_a.reset();
268   }
269 
270   {
271     impl.set_ping_handler(
272         SaveBadMessageCallback(&bindings, &bad_message_callback_b));
273     base::RunLoop loop;
274     ping_b->Ping(loop.QuitClosure());
275     loop.Run();
276   }
277 
278   std::move(bad_message_callback_a).Run("message 1");
279   EXPECT_EQ("message 1", last_received_error);
280 
281   {
282     base::RunLoop loop;
283     ping_b.set_connection_error_handler(loop.QuitClosure());
284     std::move(bad_message_callback_b).Run("message 2");
285     EXPECT_EQ("message 2", last_received_error);
286     loop.Run();
287   }
288 
289   EXPECT_TRUE(bindings.empty());
290 
291   core::SetDefaultProcessErrorCallback(mojo::core::ProcessErrorCallback());
292 }
293 
TEST_P(BindingSetTest,BindingSetGetBadMessageCallbackOutlivesBindingSet)294 TEST_P(BindingSetTest, BindingSetGetBadMessageCallbackOutlivesBindingSet) {
295   PingImpl impl;
296 
297   std::string last_received_error;
298   core::SetDefaultProcessErrorCallback(
299       base::Bind([](std::string* out_error,
300                     const std::string& error) { *out_error = error; },
301                  &last_received_error));
302 
303   ReportBadMessageCallback bad_message_callback;
304   {
305     BindingSet<PingService, int> bindings;
306     PingServicePtr ping_a;
307     bindings.AddBinding(&impl, MakeRequest(&ping_a), 1);
308 
309     impl.set_ping_handler(
310         SaveBadMessageCallback(&bindings, &bad_message_callback));
311     base::RunLoop loop;
312     ping_a->Ping(loop.QuitClosure());
313     loop.Run();
314   }
315 
316   std::move(bad_message_callback).Run("message 1");
317   EXPECT_EQ("message 1", last_received_error);
318 
319   core::SetDefaultProcessErrorCallback(mojo::core::ProcessErrorCallback());
320 }
321 
322 class PingProviderImpl : public AssociatedPingProvider, public PingService {
323  public:
PingProviderImpl()324   PingProviderImpl() {}
~PingProviderImpl()325   ~PingProviderImpl() override {}
326 
set_new_ping_context(int context)327   void set_new_ping_context(int context) { new_ping_context_ = context; }
328 
set_new_ping_handler(const base::Closure & handler)329   void set_new_ping_handler(const base::Closure& handler) {
330     new_ping_handler_ = handler;
331   }
332 
set_ping_handler(const base::Closure & handler)333   void set_ping_handler(const base::Closure& handler) {
334     ping_handler_ = handler;
335   }
336 
ping_bindings()337   AssociatedBindingSet<PingService, int>& ping_bindings() {
338     return ping_bindings_;
339   }
340 
341  private:
342   // AssociatedPingProvider:
GetPing(PingServiceAssociatedRequest request)343   void GetPing(PingServiceAssociatedRequest request) override {
344     ping_bindings_.AddBinding(this, std::move(request), new_ping_context_);
345     if (!new_ping_handler_.is_null())
346       new_ping_handler_.Run();
347   }
348 
349   // PingService:
Ping(const PingCallback & callback)350   void Ping(const PingCallback& callback) override {
351     if (!ping_handler_.is_null())
352       ping_handler_.Run();
353     callback.Run();
354   }
355 
356   AssociatedBindingSet<PingService, int> ping_bindings_;
357   int new_ping_context_ = -1;
358   base::Closure ping_handler_;
359   base::Closure new_ping_handler_;
360 };
361 
TEST_P(BindingSetTest,AssociatedBindingSetContext)362 TEST_P(BindingSetTest, AssociatedBindingSetContext) {
363   AssociatedPingProviderPtr provider;
364   PingProviderImpl impl;
365   Binding<AssociatedPingProvider> binding(&impl, MakeRequest(&provider));
366 
367   PingServiceAssociatedPtr ping_a;
368   {
369     base::RunLoop loop;
370     impl.set_new_ping_context(1);
371     impl.set_new_ping_handler(loop.QuitClosure());
372     provider->GetPing(MakeRequest(&ping_a));
373     loop.Run();
374   }
375 
376   PingServiceAssociatedPtr ping_b;
377   {
378     base::RunLoop loop;
379     impl.set_new_ping_context(2);
380     impl.set_new_ping_handler(loop.QuitClosure());
381     provider->GetPing(MakeRequest(&ping_b));
382     loop.Run();
383   }
384 
385   {
386     impl.set_ping_handler(ExpectContext(&impl.ping_bindings(), 1));
387     base::RunLoop loop;
388     ping_a->Ping(loop.QuitClosure());
389     loop.Run();
390   }
391 
392   {
393     impl.set_ping_handler(ExpectContext(&impl.ping_bindings(), 2));
394     base::RunLoop loop;
395     ping_b->Ping(loop.QuitClosure());
396     loop.Run();
397   }
398 
399   {
400     base::RunLoop loop;
401     impl.ping_bindings().set_connection_error_handler(
402         Sequence(ExpectContext(&impl.ping_bindings(), 1), loop.QuitClosure()));
403     ping_a.reset();
404     loop.Run();
405   }
406 
407   {
408     base::RunLoop loop;
409     impl.ping_bindings().set_connection_error_handler(
410         Sequence(ExpectContext(&impl.ping_bindings(), 2), loop.QuitClosure()));
411     ping_b.reset();
412     loop.Run();
413   }
414 
415   EXPECT_TRUE(impl.ping_bindings().empty());
416 }
417 
TEST_P(BindingSetTest,MasterInterfaceBindingSetContext)418 TEST_P(BindingSetTest, MasterInterfaceBindingSetContext) {
419   AssociatedPingProviderPtr provider_a, provider_b;
420   PingProviderImpl impl;
421   BindingSet<AssociatedPingProvider, int> bindings;
422 
423   bindings.AddBinding(&impl, MakeRequest(&provider_a), 1);
424   bindings.AddBinding(&impl, MakeRequest(&provider_b), 2);
425 
426   {
427     PingServiceAssociatedPtr ping;
428     base::RunLoop loop;
429     impl.set_new_ping_handler(
430         Sequence(ExpectContext(&bindings, 1), loop.QuitClosure()));
431     provider_a->GetPing(MakeRequest(&ping));
432     loop.Run();
433   }
434 
435   {
436     PingServiceAssociatedPtr ping;
437     base::RunLoop loop;
438     impl.set_new_ping_handler(
439         Sequence(ExpectContext(&bindings, 2), loop.QuitClosure()));
440     provider_b->GetPing(MakeRequest(&ping));
441     loop.Run();
442   }
443 
444   {
445     base::RunLoop loop;
446     bindings.set_connection_error_handler(
447         Sequence(ExpectContext(&bindings, 1), loop.QuitClosure()));
448     provider_a.reset();
449     loop.Run();
450   }
451 
452   {
453     base::RunLoop loop;
454     bindings.set_connection_error_handler(
455         Sequence(ExpectContext(&bindings, 2), loop.QuitClosure()));
456     provider_b.reset();
457     loop.Run();
458   }
459 
460   EXPECT_TRUE(bindings.empty());
461 }
462 
TEST_P(BindingSetTest,MasterInterfaceBindingSetDispatchBinding)463 TEST_P(BindingSetTest, MasterInterfaceBindingSetDispatchBinding) {
464   AssociatedPingProviderPtr provider_a, provider_b;
465   PingProviderImpl impl;
466   BindingSet<AssociatedPingProvider, int> bindings;
467 
468   BindingId id_a = bindings.AddBinding(&impl, MakeRequest(&provider_a), 1);
469   BindingId id_b = bindings.AddBinding(&impl, MakeRequest(&provider_b), 2);
470 
471   {
472     PingServiceAssociatedPtr ping;
473     base::RunLoop loop;
474     impl.set_new_ping_handler(
475         Sequence(ExpectBindingId(&bindings, id_a), loop.QuitClosure()));
476     provider_a->GetPing(MakeRequest(&ping));
477     loop.Run();
478   }
479 
480   {
481     PingServiceAssociatedPtr ping;
482     base::RunLoop loop;
483     impl.set_new_ping_handler(
484         Sequence(ExpectBindingId(&bindings, id_b), loop.QuitClosure()));
485     provider_b->GetPing(MakeRequest(&ping));
486     loop.Run();
487   }
488 
489   {
490     base::RunLoop loop;
491     bindings.set_connection_error_handler(
492         Sequence(ExpectBindingId(&bindings, id_a), loop.QuitClosure()));
493     provider_a.reset();
494     loop.Run();
495   }
496 
497   {
498     base::RunLoop loop;
499     bindings.set_connection_error_handler(
500         Sequence(ExpectBindingId(&bindings, id_b), loop.QuitClosure()));
501     provider_b.reset();
502     loop.Run();
503   }
504 
505   EXPECT_TRUE(bindings.empty());
506 }
507 
TEST_P(BindingSetTest,PreDispatchHandler)508 TEST_P(BindingSetTest, PreDispatchHandler) {
509   PingImpl impl;
510 
511   BindingSet<PingService, int> bindings;
512   PingServicePtr ping_a, ping_b;
513   bindings.AddBinding(&impl, MakeRequest(&ping_a), 1);
514   bindings.AddBinding(&impl, MakeRequest(&ping_b), 2);
515 
516   {
517     bindings.set_pre_dispatch_handler(base::Bind([] (const int& context) {
518       EXPECT_EQ(1, context);
519     }));
520     base::RunLoop loop;
521     ping_a->Ping(loop.QuitClosure());
522     loop.Run();
523   }
524 
525   {
526     bindings.set_pre_dispatch_handler(base::Bind([] (const int& context) {
527       EXPECT_EQ(2, context);
528     }));
529     base::RunLoop loop;
530     ping_b->Ping(loop.QuitClosure());
531     loop.Run();
532   }
533 
534   {
535     base::RunLoop loop;
536     bindings.set_pre_dispatch_handler(
537         base::Bind([](base::RunLoop* loop, const int& context) {
538           EXPECT_EQ(1, context);
539           loop->Quit();
540         }, &loop));
541     ping_a.reset();
542     loop.Run();
543   }
544 
545   {
546     base::RunLoop loop;
547     bindings.set_pre_dispatch_handler(
548         base::Bind([](base::RunLoop* loop, const int& context) {
549           EXPECT_EQ(2, context);
550           loop->Quit();
551         }, &loop));
552     ping_b.reset();
553     loop.Run();
554   }
555 
556   EXPECT_TRUE(bindings.empty());
557 }
558 
TEST_P(BindingSetTest,AssociatedBindingSetConnectionErrorWithReason)559 TEST_P(BindingSetTest, AssociatedBindingSetConnectionErrorWithReason) {
560   AssociatedPingProviderPtr master_ptr;
561   PingProviderImpl master_impl;
562   Binding<AssociatedPingProvider> master_binding(&master_impl,
563                                                  MakeRequest(&master_ptr));
564 
565   base::RunLoop run_loop;
566   master_impl.ping_bindings().set_connection_error_with_reason_handler(
567       base::Bind(
568           [](const base::Closure& quit_closure, uint32_t custom_reason,
569              const std::string& description) {
570             EXPECT_EQ(2048u, custom_reason);
571             EXPECT_EQ("bye", description);
572             quit_closure.Run();
573           },
574           run_loop.QuitClosure()));
575 
576   PingServiceAssociatedPtr ptr;
577   master_ptr->GetPing(MakeRequest(&ptr));
578 
579   ptr.ResetWithReason(2048u, "bye");
580 
581   run_loop.Run();
582 }
583 
584 class PingInstanceCounter : public PingService {
585  public:
PingInstanceCounter()586   PingInstanceCounter() { ++instance_count; }
~PingInstanceCounter()587   ~PingInstanceCounter() override { --instance_count; }
588 
Ping(const PingCallback & callback)589   void Ping(const PingCallback& callback) override {}
590 
591   static int instance_count;
592 };
593 int PingInstanceCounter::instance_count = 0;
594 
TEST_P(BindingSetTest,StrongBinding_Destructor)595 TEST_P(BindingSetTest, StrongBinding_Destructor) {
596   PingServicePtr ping_a, ping_b;
597   auto bindings = std::make_unique<StrongBindingSet<PingService>>();
598 
599   bindings->AddBinding(std::make_unique<PingInstanceCounter>(),
600                        mojo::MakeRequest(&ping_a));
601   EXPECT_EQ(1, PingInstanceCounter::instance_count);
602 
603   bindings->AddBinding(std::make_unique<PingInstanceCounter>(),
604                        mojo::MakeRequest(&ping_b));
605   EXPECT_EQ(2, PingInstanceCounter::instance_count);
606 
607   bindings.reset();
608   EXPECT_EQ(0, PingInstanceCounter::instance_count);
609 }
610 
TEST_P(BindingSetTest,StrongBinding_ConnectionError)611 TEST_P(BindingSetTest, StrongBinding_ConnectionError) {
612   PingServicePtr ping_a, ping_b;
613   StrongBindingSet<PingService> bindings;
614   bindings.AddBinding(std::make_unique<PingInstanceCounter>(),
615                       mojo::MakeRequest(&ping_a));
616   bindings.AddBinding(std::make_unique<PingInstanceCounter>(),
617                       mojo::MakeRequest(&ping_b));
618   EXPECT_EQ(2, PingInstanceCounter::instance_count);
619 
620   ping_a.reset();
621   base::RunLoop().RunUntilIdle();
622   EXPECT_EQ(1, PingInstanceCounter::instance_count);
623 
624   ping_b.reset();
625   base::RunLoop().RunUntilIdle();
626   EXPECT_EQ(0, PingInstanceCounter::instance_count);
627 }
628 
TEST_P(BindingSetTest,StrongBinding_RemoveBinding)629 TEST_P(BindingSetTest, StrongBinding_RemoveBinding) {
630   PingServicePtr ping_a, ping_b;
631   StrongBindingSet<PingService> bindings;
632   BindingId binding_id_a = bindings.AddBinding(
633       std::make_unique<PingInstanceCounter>(), mojo::MakeRequest(&ping_a));
634   BindingId binding_id_b = bindings.AddBinding(
635       std::make_unique<PingInstanceCounter>(), mojo::MakeRequest(&ping_b));
636   EXPECT_EQ(2, PingInstanceCounter::instance_count);
637 
638   EXPECT_TRUE(bindings.RemoveBinding(binding_id_a));
639   EXPECT_EQ(1, PingInstanceCounter::instance_count);
640 
641   EXPECT_TRUE(bindings.RemoveBinding(binding_id_b));
642   EXPECT_EQ(0, PingInstanceCounter::instance_count);
643 }
644 
645 INSTANTIATE_MOJO_BINDINGS_TEST_CASE_P(BindingSetTest);
646 
647 }  // namespace
648 }  // namespace test
649 }  // namespace mojo
650