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