• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "base/bind.h"
6 #include "base/callback.h"
7 #include "base/logging.h"
8 #include "base/memory/ptr_util.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/run_loop.h"
11 #include "mojo/public/cpp/bindings/binding_set.h"
12 #include "mojo/public/cpp/bindings/interface_request.h"
13 #include "mojo/public/cpp/bindings/tests/rect_blink.h"
14 #include "mojo/public/cpp/bindings/tests/rect_chromium.h"
15 #include "mojo/public/cpp/bindings/tests/struct_with_traits_impl.h"
16 #include "mojo/public/cpp/bindings/tests/struct_with_traits_impl_traits.h"
17 #include "mojo/public/cpp/bindings/tests/variant_test_util.h"
18 #include "mojo/public/cpp/system/wait.h"
19 #include "mojo/public/interfaces/bindings/tests/struct_with_traits.mojom.h"
20 #include "mojo/public/interfaces/bindings/tests/test_native_types.mojom-blink.h"
21 #include "mojo/public/interfaces/bindings/tests/test_native_types.mojom.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23 
24 namespace mojo {
25 namespace test {
26 namespace {
27 
28 template <typename T>
DoExpectResult(const T & expected,const base::Closure & callback,const T & actual)29 void DoExpectResult(const T& expected,
30                     const base::Closure& callback,
31                     const T& actual) {
32   EXPECT_EQ(expected.x(), actual.x());
33   EXPECT_EQ(expected.y(), actual.y());
34   EXPECT_EQ(expected.width(), actual.width());
35   EXPECT_EQ(expected.height(), actual.height());
36   callback.Run();
37 }
38 
39 template <typename T>
ExpectResult(const T & r,const base::Closure & callback)40 base::Callback<void(const T&)> ExpectResult(const T& r,
41                                             const base::Closure& callback) {
42   return base::Bind(&DoExpectResult<T>, r, callback);
43 }
44 
45 template <typename T>
DoFail(const std::string & reason,const T &)46 void DoFail(const std::string& reason, const T&) {
47   EXPECT_TRUE(false) << reason;
48 }
49 
50 template <typename T>
Fail(const std::string & reason)51 base::Callback<void(const T&)> Fail(const std::string& reason) {
52   return base::Bind(&DoFail<T>, reason);
53 }
54 
55 template <typename T>
ExpectError(InterfacePtr<T> * proxy,const base::Closure & callback)56 void ExpectError(InterfacePtr<T> *proxy, const base::Closure& callback) {
57   proxy->set_connection_error_handler(callback);
58 }
59 
60 // This implements the generated Chromium variant of RectService.
61 class ChromiumRectServiceImpl : public RectService {
62  public:
ChromiumRectServiceImpl()63   ChromiumRectServiceImpl() {}
64 
65   // mojo::test::RectService:
AddRect(const RectChromium & r)66   void AddRect(const RectChromium& r) override {
67     if (r.GetArea() > largest_rect_.GetArea())
68       largest_rect_ = r;
69   }
70 
GetLargestRect(const GetLargestRectCallback & callback)71   void GetLargestRect(const GetLargestRectCallback& callback) override {
72     callback.Run(largest_rect_);
73   }
74 
PassSharedRect(const SharedRect & r,const PassSharedRectCallback & callback)75   void PassSharedRect(const SharedRect& r,
76                       const PassSharedRectCallback& callback) override {
77     callback.Run(r);
78   }
79 
80  private:
81   RectChromium largest_rect_;
82 };
83 
84 // This implements the generated Blink variant of RectService.
85 class BlinkRectServiceImpl : public blink::RectService {
86  public:
BlinkRectServiceImpl()87   BlinkRectServiceImpl() {}
88 
89   // mojo::test::blink::RectService:
AddRect(const RectBlink & r)90   void AddRect(const RectBlink& r) override {
91     if (r.computeArea() > largest_rect_.computeArea()) {
92       largest_rect_.setX(r.x());
93       largest_rect_.setY(r.y());
94       largest_rect_.setWidth(r.width());
95       largest_rect_.setHeight(r.height());
96     }
97   }
98 
GetLargestRect(const GetLargestRectCallback & callback)99   void GetLargestRect(const GetLargestRectCallback& callback) override {
100     callback.Run(largest_rect_);
101   }
102 
PassSharedRect(const SharedRect & r,const PassSharedRectCallback & callback)103   void PassSharedRect(const SharedRect& r,
104                       const PassSharedRectCallback& callback) override {
105     callback.Run(r);
106   }
107 
108  private:
109   RectBlink largest_rect_;
110 };
111 
112 // A test which runs both Chromium and Blink implementations of a RectService.
113 class StructTraitsTest : public testing::Test,
114                          public TraitsTestService {
115  public:
StructTraitsTest()116   StructTraitsTest() {}
117 
118  protected:
BindToChromiumService(RectServiceRequest request)119   void BindToChromiumService(RectServiceRequest request) {
120     chromium_bindings_.AddBinding(&chromium_service_, std::move(request));
121   }
BindToChromiumService(blink::RectServiceRequest request)122   void BindToChromiumService(blink::RectServiceRequest request) {
123     chromium_bindings_.AddBinding(
124         &chromium_service_,
125         ConvertInterfaceRequest<RectService>(std::move(request)));
126   }
127 
BindToBlinkService(blink::RectServiceRequest request)128   void BindToBlinkService(blink::RectServiceRequest request) {
129     blink_bindings_.AddBinding(&blink_service_, std::move(request));
130   }
BindToBlinkService(RectServiceRequest request)131   void BindToBlinkService(RectServiceRequest request) {
132     blink_bindings_.AddBinding(
133         &blink_service_,
134         ConvertInterfaceRequest<blink::RectService>(std::move(request)));
135   }
136 
GetTraitsTestProxy()137   TraitsTestServicePtr GetTraitsTestProxy() {
138     TraitsTestServicePtr proxy;
139     traits_test_bindings_.AddBinding(this, mojo::MakeRequest(&proxy));
140     return proxy;
141   }
142 
143  private:
144   // TraitsTestService:
EchoStructWithTraits(const StructWithTraitsImpl & s,const EchoStructWithTraitsCallback & callback)145   void EchoStructWithTraits(
146       const StructWithTraitsImpl& s,
147       const EchoStructWithTraitsCallback& callback) override {
148     callback.Run(s);
149   }
150 
EchoTrivialStructWithTraits(TrivialStructWithTraitsImpl s,const EchoTrivialStructWithTraitsCallback & callback)151   void EchoTrivialStructWithTraits(
152       TrivialStructWithTraitsImpl s,
153       const EchoTrivialStructWithTraitsCallback& callback) override {
154     callback.Run(s);
155   }
156 
EchoMoveOnlyStructWithTraits(MoveOnlyStructWithTraitsImpl s,const EchoMoveOnlyStructWithTraitsCallback & callback)157   void EchoMoveOnlyStructWithTraits(
158       MoveOnlyStructWithTraitsImpl s,
159       const EchoMoveOnlyStructWithTraitsCallback& callback) override {
160     callback.Run(std::move(s));
161   }
162 
EchoNullableMoveOnlyStructWithTraits(base::Optional<MoveOnlyStructWithTraitsImpl> s,const EchoNullableMoveOnlyStructWithTraitsCallback & callback)163   void EchoNullableMoveOnlyStructWithTraits(
164       base::Optional<MoveOnlyStructWithTraitsImpl> s,
165       const EchoNullableMoveOnlyStructWithTraitsCallback& callback) override {
166     callback.Run(std::move(s));
167   }
168 
EchoEnumWithTraits(EnumWithTraitsImpl e,const EchoEnumWithTraitsCallback & callback)169   void EchoEnumWithTraits(EnumWithTraitsImpl e,
170                           const EchoEnumWithTraitsCallback& callback) override {
171     callback.Run(e);
172   }
173 
EchoStructWithTraitsForUniquePtr(std::unique_ptr<int> e,const EchoStructWithTraitsForUniquePtrCallback & callback)174   void EchoStructWithTraitsForUniquePtr(
175       std::unique_ptr<int> e,
176       const EchoStructWithTraitsForUniquePtrCallback& callback) override {
177     callback.Run(std::move(e));
178   }
179 
EchoNullableStructWithTraitsForUniquePtr(std::unique_ptr<int> e,const EchoNullableStructWithTraitsForUniquePtrCallback & callback)180   void EchoNullableStructWithTraitsForUniquePtr(
181       std::unique_ptr<int> e,
182       const EchoNullableStructWithTraitsForUniquePtrCallback& callback)
183       override {
184     callback.Run(std::move(e));
185   }
186 
EchoUnionWithTraits(std::unique_ptr<test::UnionWithTraitsBase> u,const EchoUnionWithTraitsCallback & callback)187   void EchoUnionWithTraits(
188       std::unique_ptr<test::UnionWithTraitsBase> u,
189       const EchoUnionWithTraitsCallback& callback) override {
190     callback.Run(std::move(u));
191   }
192 
193   base::MessageLoop loop_;
194 
195   ChromiumRectServiceImpl chromium_service_;
196   BindingSet<RectService> chromium_bindings_;
197 
198   BlinkRectServiceImpl blink_service_;
199   BindingSet<blink::RectService> blink_bindings_;
200 
201   BindingSet<TraitsTestService> traits_test_bindings_;
202 };
203 
204 }  // namespace
205 
TEST_F(StructTraitsTest,ChromiumProxyToChromiumService)206 TEST_F(StructTraitsTest, ChromiumProxyToChromiumService) {
207   RectServicePtr chromium_proxy;
208   BindToChromiumService(MakeRequest(&chromium_proxy));
209   {
210     base::RunLoop loop;
211     chromium_proxy->AddRect(RectChromium(1, 1, 4, 5));
212     chromium_proxy->AddRect(RectChromium(-1, -1, 2, 2));
213     chromium_proxy->GetLargestRect(
214         ExpectResult(RectChromium(1, 1, 4, 5), loop.QuitClosure()));
215     loop.Run();
216   }
217   {
218     base::RunLoop loop;
219     chromium_proxy->PassSharedRect(
220         {1, 2, 3, 4},
221         ExpectResult(SharedRect({1, 2, 3, 4}), loop.QuitClosure()));
222     loop.Run();
223   }
224 }
225 
TEST_F(StructTraitsTest,ChromiumToBlinkService)226 TEST_F(StructTraitsTest, ChromiumToBlinkService) {
227   RectServicePtr chromium_proxy;
228   BindToBlinkService(MakeRequest(&chromium_proxy));
229   {
230     base::RunLoop loop;
231     chromium_proxy->AddRect(RectChromium(1, 1, 4, 5));
232     chromium_proxy->AddRect(RectChromium(2, 2, 5, 5));
233     chromium_proxy->GetLargestRect(
234         ExpectResult(RectChromium(2, 2, 5, 5), loop.QuitClosure()));
235     loop.Run();
236   }
237   {
238     base::RunLoop loop;
239     chromium_proxy->PassSharedRect(
240         {1, 2, 3, 4},
241         ExpectResult(SharedRect({1, 2, 3, 4}), loop.QuitClosure()));
242     loop.Run();
243   }
244   // The Blink service should drop our connection because RectBlink's
245   // deserializer rejects negative origins.
246   {
247     base::RunLoop loop;
248     ExpectError(&chromium_proxy, loop.QuitClosure());
249     chromium_proxy->AddRect(RectChromium(-1, -1, 2, 2));
250     chromium_proxy->GetLargestRect(
251         Fail<RectChromium>("The pipe should have been closed."));
252     loop.Run();
253   }
254 }
255 
TEST_F(StructTraitsTest,BlinkProxyToBlinkService)256 TEST_F(StructTraitsTest, BlinkProxyToBlinkService) {
257   blink::RectServicePtr blink_proxy;
258   BindToBlinkService(MakeRequest(&blink_proxy));
259   {
260     base::RunLoop loop;
261     blink_proxy->AddRect(RectBlink(1, 1, 4, 5));
262     blink_proxy->AddRect(RectBlink(10, 10, 20, 20));
263     blink_proxy->GetLargestRect(
264         ExpectResult(RectBlink(10, 10, 20, 20), loop.QuitClosure()));
265     loop.Run();
266   }
267   {
268     base::RunLoop loop;
269     blink_proxy->PassSharedRect(
270         {4, 3, 2, 1},
271         ExpectResult(SharedRect({4, 3, 2, 1}), loop.QuitClosure()));
272     loop.Run();
273   }
274 }
275 
TEST_F(StructTraitsTest,BlinkProxyToChromiumService)276 TEST_F(StructTraitsTest, BlinkProxyToChromiumService) {
277   blink::RectServicePtr blink_proxy;
278   BindToChromiumService(MakeRequest(&blink_proxy));
279   {
280     base::RunLoop loop;
281     blink_proxy->AddRect(RectBlink(1, 1, 4, 5));
282     blink_proxy->AddRect(RectBlink(10, 10, 2, 2));
283     blink_proxy->GetLargestRect(
284         ExpectResult(RectBlink(1, 1, 4, 5), loop.QuitClosure()));
285     loop.Run();
286   }
287   {
288     base::RunLoop loop;
289     blink_proxy->PassSharedRect(
290         {4, 3, 2, 1},
291         ExpectResult(SharedRect({4, 3, 2, 1}), loop.QuitClosure()));
292     loop.Run();
293   }
294 }
295 
ExpectStructWithTraits(const StructWithTraitsImpl & expected,const base::Closure & closure,const StructWithTraitsImpl & passed)296 void ExpectStructWithTraits(const StructWithTraitsImpl& expected,
297                             const base::Closure& closure,
298                             const StructWithTraitsImpl& passed) {
299   EXPECT_EQ(expected.get_enum(), passed.get_enum());
300   EXPECT_EQ(expected.get_bool(), passed.get_bool());
301   EXPECT_EQ(expected.get_uint32(), passed.get_uint32());
302   EXPECT_EQ(expected.get_uint64(), passed.get_uint64());
303   EXPECT_EQ(expected.get_string(), passed.get_string());
304   EXPECT_EQ(expected.get_string_array(), passed.get_string_array());
305   EXPECT_EQ(expected.get_struct(), passed.get_struct());
306   EXPECT_EQ(expected.get_struct_array(), passed.get_struct_array());
307   EXPECT_EQ(expected.get_struct_map(), passed.get_struct_map());
308   closure.Run();
309 }
310 
TEST_F(StructTraitsTest,EchoStructWithTraits)311 TEST_F(StructTraitsTest, EchoStructWithTraits) {
312   StructWithTraitsImpl input;
313   input.set_enum(EnumWithTraitsImpl::CUSTOM_VALUE_1);
314   input.set_bool(true);
315   input.set_uint32(7);
316   input.set_uint64(42);
317   input.set_string("hello world!");
318   input.get_mutable_string_array().assign({"hello", "world!"});
319   input.get_mutable_string_set().insert("hello");
320   input.get_mutable_string_set().insert("world!");
321   input.get_mutable_struct().value = 42;
322   input.get_mutable_struct_array().resize(2);
323   input.get_mutable_struct_array()[0].value = 1;
324   input.get_mutable_struct_array()[1].value = 2;
325   input.get_mutable_struct_map()["hello"] = NestedStructWithTraitsImpl(1024);
326   input.get_mutable_struct_map()["world"] = NestedStructWithTraitsImpl(2048);
327 
328   base::RunLoop loop;
329   TraitsTestServicePtr proxy = GetTraitsTestProxy();
330 
331   proxy->EchoStructWithTraits(
332       input,
333       base::Bind(&ExpectStructWithTraits, input, loop.QuitClosure()));
334   loop.Run();
335 }
336 
TEST_F(StructTraitsTest,CloneStructWithTraitsContainer)337 TEST_F(StructTraitsTest, CloneStructWithTraitsContainer) {
338   StructWithTraitsContainerPtr container = StructWithTraitsContainer::New();
339   container->f_struct.set_uint32(7);
340   container->f_struct.set_uint64(42);
341   StructWithTraitsContainerPtr cloned_container = container.Clone();
342   EXPECT_EQ(7u, cloned_container->f_struct.get_uint32());
343   EXPECT_EQ(42u, cloned_container->f_struct.get_uint64());
344 }
345 
ExpectTrivialStructWithTraits(TrivialStructWithTraitsImpl expected,const base::Closure & closure,TrivialStructWithTraitsImpl passed)346 void ExpectTrivialStructWithTraits(TrivialStructWithTraitsImpl expected,
347                                    const base::Closure& closure,
348                                    TrivialStructWithTraitsImpl passed) {
349   EXPECT_EQ(expected.value, passed.value);
350   closure.Run();
351 }
352 
TEST_F(StructTraitsTest,EchoTrivialStructWithTraits)353 TEST_F(StructTraitsTest, EchoTrivialStructWithTraits) {
354   TrivialStructWithTraitsImpl input;
355   input.value = 42;
356 
357   base::RunLoop loop;
358   TraitsTestServicePtr proxy = GetTraitsTestProxy();
359 
360   proxy->EchoTrivialStructWithTraits(
361       input,
362       base::Bind(&ExpectTrivialStructWithTraits, input, loop.QuitClosure()));
363   loop.Run();
364 }
365 
CaptureMessagePipe(ScopedMessagePipeHandle * storage,const base::Closure & closure,MoveOnlyStructWithTraitsImpl passed)366 void CaptureMessagePipe(ScopedMessagePipeHandle* storage,
367                         const base::Closure& closure,
368                         MoveOnlyStructWithTraitsImpl passed) {
369   storage->reset(MessagePipeHandle(
370       passed.get_mutable_handle().release().value()));
371   closure.Run();
372 }
373 
TEST_F(StructTraitsTest,EchoMoveOnlyStructWithTraits)374 TEST_F(StructTraitsTest, EchoMoveOnlyStructWithTraits) {
375   MessagePipe mp;
376   MoveOnlyStructWithTraitsImpl input;
377   input.get_mutable_handle().reset(mp.handle0.release());
378 
379   base::RunLoop loop;
380   TraitsTestServicePtr proxy = GetTraitsTestProxy();
381 
382   ScopedMessagePipeHandle received;
383   proxy->EchoMoveOnlyStructWithTraits(
384       std::move(input),
385       base::Bind(&CaptureMessagePipe, &received, loop.QuitClosure()));
386   loop.Run();
387 
388   ASSERT_TRUE(received.is_valid());
389 
390   // Verify that the message pipe handle is correctly passed.
391   const char kHello[] = "hello";
392   const uint32_t kHelloSize = static_cast<uint32_t>(sizeof(kHello));
393   EXPECT_EQ(MOJO_RESULT_OK,
394             WriteMessageRaw(mp.handle1.get(), kHello, kHelloSize, nullptr, 0,
395                             MOJO_WRITE_MESSAGE_FLAG_NONE));
396 
397   EXPECT_EQ(MOJO_RESULT_OK, Wait(received.get(), MOJO_HANDLE_SIGNAL_READABLE));
398 
399   std::vector<uint8_t> bytes;
400   std::vector<ScopedHandle> handles;
401   EXPECT_EQ(MOJO_RESULT_OK, ReadMessageRaw(received.get(), &bytes, &handles,
402                                            MOJO_READ_MESSAGE_FLAG_NONE));
403   EXPECT_EQ(kHelloSize, bytes.size());
404   EXPECT_STREQ(kHello, reinterpret_cast<char*>(bytes.data()));
405 }
406 
CaptureNullableMoveOnlyStructWithTraitsImpl(base::Optional<MoveOnlyStructWithTraitsImpl> * storage,const base::Closure & closure,base::Optional<MoveOnlyStructWithTraitsImpl> passed)407 void CaptureNullableMoveOnlyStructWithTraitsImpl(
408     base::Optional<MoveOnlyStructWithTraitsImpl>* storage,
409     const base::Closure& closure,
410     base::Optional<MoveOnlyStructWithTraitsImpl> passed) {
411   *storage = std::move(passed);
412   closure.Run();
413 }
414 
TEST_F(StructTraitsTest,EchoNullableMoveOnlyStructWithTraits)415 TEST_F(StructTraitsTest, EchoNullableMoveOnlyStructWithTraits) {
416   base::RunLoop loop;
417   TraitsTestServicePtr proxy = GetTraitsTestProxy();
418 
419   base::Optional<MoveOnlyStructWithTraitsImpl> received;
420   proxy->EchoNullableMoveOnlyStructWithTraits(
421       base::nullopt, base::Bind(&CaptureNullableMoveOnlyStructWithTraitsImpl,
422                                 &received, loop.QuitClosure()));
423   loop.Run();
424 
425   EXPECT_FALSE(received);
426 }
427 
ExpectEnumWithTraits(EnumWithTraitsImpl expected_value,const base::Closure & closure,EnumWithTraitsImpl value)428 void ExpectEnumWithTraits(EnumWithTraitsImpl expected_value,
429                           const base::Closure& closure,
430                           EnumWithTraitsImpl value) {
431   EXPECT_EQ(expected_value, value);
432   closure.Run();
433 }
434 
TEST_F(StructTraitsTest,EchoEnumWithTraits)435 TEST_F(StructTraitsTest, EchoEnumWithTraits) {
436   base::RunLoop loop;
437   TraitsTestServicePtr proxy = GetTraitsTestProxy();
438 
439   proxy->EchoEnumWithTraits(
440       EnumWithTraitsImpl::CUSTOM_VALUE_1,
441       base::Bind(&ExpectEnumWithTraits, EnumWithTraitsImpl::CUSTOM_VALUE_1,
442                  loop.QuitClosure()));
443   loop.Run();
444 }
445 
TEST_F(StructTraitsTest,SerializeStructWithTraits)446 TEST_F(StructTraitsTest, SerializeStructWithTraits) {
447   StructWithTraitsImpl input;
448   input.set_enum(EnumWithTraitsImpl::CUSTOM_VALUE_1);
449   input.set_bool(true);
450   input.set_uint32(7);
451   input.set_uint64(42);
452   input.set_string("hello world!");
453   input.get_mutable_string_array().assign({ "hello", "world!" });
454   input.get_mutable_string_set().insert("hello");
455   input.get_mutable_string_set().insert("world!");
456   input.get_mutable_struct().value = 42;
457   input.get_mutable_struct_array().resize(2);
458   input.get_mutable_struct_array()[0].value = 1;
459   input.get_mutable_struct_array()[1].value = 2;
460   input.get_mutable_struct_map()["hello"] = NestedStructWithTraitsImpl(1024);
461   input.get_mutable_struct_map()["world"] = NestedStructWithTraitsImpl(2048);
462 
463   auto data = StructWithTraits::Serialize(&input);
464   StructWithTraitsImpl output;
465   ASSERT_TRUE(StructWithTraits::Deserialize(std::move(data), &output));
466 
467   EXPECT_EQ(input.get_enum(), output.get_enum());
468   EXPECT_EQ(input.get_bool(), output.get_bool());
469   EXPECT_EQ(input.get_uint32(), output.get_uint32());
470   EXPECT_EQ(input.get_uint64(), output.get_uint64());
471   EXPECT_EQ(input.get_string(), output.get_string());
472   EXPECT_EQ(input.get_string_array(), output.get_string_array());
473   EXPECT_EQ(input.get_string_set(), output.get_string_set());
474   EXPECT_EQ(input.get_struct(), output.get_struct());
475   EXPECT_EQ(input.get_struct_array(), output.get_struct_array());
476   EXPECT_EQ(input.get_struct_map(), output.get_struct_map());
477 }
478 
ExpectUniquePtr(std::unique_ptr<int> expected,const base::Closure & closure,std::unique_ptr<int> value)479 void ExpectUniquePtr(std::unique_ptr<int> expected,
480                      const base::Closure& closure,
481                      std::unique_ptr<int> value) {
482   ASSERT_EQ(!expected, !value);
483   if (expected)
484     EXPECT_EQ(*expected, *value);
485   closure.Run();
486 }
487 
TEST_F(StructTraitsTest,TypemapUniquePtr)488 TEST_F(StructTraitsTest, TypemapUniquePtr) {
489   TraitsTestServicePtr proxy = GetTraitsTestProxy();
490 
491   {
492     base::RunLoop loop;
493     proxy->EchoStructWithTraitsForUniquePtr(
494         std::make_unique<int>(12345),
495         base::Bind(&ExpectUniquePtr, base::Passed(std::make_unique<int>(12345)),
496                    loop.QuitClosure()));
497     loop.Run();
498   }
499   {
500     base::RunLoop loop;
501     proxy->EchoNullableStructWithTraitsForUniquePtr(
502         nullptr, base::Bind(&ExpectUniquePtr, nullptr, loop.QuitClosure()));
503     loop.Run();
504   }
505 }
506 
TEST_F(StructTraitsTest,EchoUnionWithTraits)507 TEST_F(StructTraitsTest, EchoUnionWithTraits) {
508   TraitsTestServicePtr proxy = GetTraitsTestProxy();
509 
510   {
511     std::unique_ptr<test::UnionWithTraitsBase> input(
512         new test::UnionWithTraitsInt32(1234));
513     base::RunLoop loop;
514     proxy->EchoUnionWithTraits(
515         std::move(input),
516         base::Bind(
517             [](const base::Closure& quit_closure,
518                std::unique_ptr<test::UnionWithTraitsBase> passed) {
519               ASSERT_EQ(test::UnionWithTraitsBase::Type::INT32, passed->type());
520               EXPECT_EQ(1234,
521                         static_cast<test::UnionWithTraitsInt32*>(passed.get())
522                             ->value());
523               quit_closure.Run();
524 
525             },
526             loop.QuitClosure()));
527     loop.Run();
528   }
529 
530   {
531     std::unique_ptr<test::UnionWithTraitsBase> input(
532         new test::UnionWithTraitsStruct(4321));
533     base::RunLoop loop;
534     proxy->EchoUnionWithTraits(
535         std::move(input),
536         base::Bind(
537             [](const base::Closure& quit_closure,
538                std::unique_ptr<test::UnionWithTraitsBase> passed) {
539               ASSERT_EQ(test::UnionWithTraitsBase::Type::STRUCT,
540                         passed->type());
541               EXPECT_EQ(4321,
542                         static_cast<test::UnionWithTraitsStruct*>(passed.get())
543                             ->get_struct()
544                             .value);
545               quit_closure.Run();
546 
547             },
548             loop.QuitClosure()));
549     loop.Run();
550   }
551 }
552 
TEST_F(StructTraitsTest,DefaultValueOfEnumWithTraits)553 TEST_F(StructTraitsTest, DefaultValueOfEnumWithTraits) {
554   auto container = EnumWithTraitsContainer::New();
555   EXPECT_EQ(EnumWithTraitsImpl::CUSTOM_VALUE_1, container->f_field);
556 }
557 
558 }  // namespace test
559 }  // namespace mojo
560