1 // Copyright 2014 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 <stddef.h>
6 #include <stdint.h>
7 #include <utility>
8 #include <vector>
9 
10 #include "base/message_loop/message_loop.h"
11 #include "base/run_loop.h"
12 #include "mojo/public/cpp/bindings/array.h"
13 #include "mojo/public/cpp/bindings/binding.h"
14 #include "mojo/public/cpp/bindings/lib/array_internal.h"
15 #include "mojo/public/cpp/bindings/lib/fixed_buffer.h"
16 #include "mojo/public/cpp/bindings/lib/serialization.h"
17 #include "mojo/public/cpp/bindings/lib/validation_context.h"
18 #include "mojo/public/cpp/bindings/lib/validation_errors.h"
19 #include "mojo/public/cpp/bindings/string.h"
20 #include "mojo/public/cpp/test_support/test_utils.h"
21 #include "mojo/public/interfaces/bindings/tests/test_structs.mojom.h"
22 #include "mojo/public/interfaces/bindings/tests/test_unions.mojom.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24 
25 namespace mojo {
26 namespace test {
27 
TEST(UnionTest,PlainOldDataGetterSetter)28 TEST(UnionTest, PlainOldDataGetterSetter) {
29   PodUnionPtr pod(PodUnion::New());
30 
31   pod->set_f_int8(10);
32   EXPECT_EQ(10, pod->get_f_int8());
33   EXPECT_TRUE(pod->is_f_int8());
34   EXPECT_FALSE(pod->is_f_int8_other());
35   EXPECT_EQ(pod->which(), PodUnion::Tag::F_INT8);
36 
37   pod->set_f_uint8(11);
38   EXPECT_EQ(11, pod->get_f_uint8());
39   EXPECT_TRUE(pod->is_f_uint8());
40   EXPECT_FALSE(pod->is_f_int8());
41   EXPECT_EQ(pod->which(), PodUnion::Tag::F_UINT8);
42 
43   pod->set_f_int16(12);
44   EXPECT_EQ(12, pod->get_f_int16());
45   EXPECT_TRUE(pod->is_f_int16());
46   EXPECT_EQ(pod->which(), PodUnion::Tag::F_INT16);
47 
48   pod->set_f_uint16(13);
49   EXPECT_EQ(13, pod->get_f_uint16());
50   EXPECT_TRUE(pod->is_f_uint16());
51   EXPECT_EQ(pod->which(), PodUnion::Tag::F_UINT16);
52 
53   pod->set_f_int32(14);
54   EXPECT_EQ(14, pod->get_f_int32());
55   EXPECT_TRUE(pod->is_f_int32());
56   EXPECT_EQ(pod->which(), PodUnion::Tag::F_INT32);
57 
58   pod->set_f_uint32(static_cast<uint32_t>(15));
59   EXPECT_EQ(static_cast<uint32_t>(15), pod->get_f_uint32());
60   EXPECT_TRUE(pod->is_f_uint32());
61   EXPECT_EQ(pod->which(), PodUnion::Tag::F_UINT32);
62 
63   pod->set_f_int64(16);
64   EXPECT_EQ(16, pod->get_f_int64());
65   EXPECT_TRUE(pod->is_f_int64());
66   EXPECT_EQ(pod->which(), PodUnion::Tag::F_INT64);
67 
68   pod->set_f_uint64(static_cast<uint64_t>(17));
69   EXPECT_EQ(static_cast<uint64_t>(17), pod->get_f_uint64());
70   EXPECT_TRUE(pod->is_f_uint64());
71   EXPECT_EQ(pod->which(), PodUnion::Tag::F_UINT64);
72 
73   pod->set_f_float(1.5);
74   EXPECT_EQ(1.5, pod->get_f_float());
75   EXPECT_TRUE(pod->is_f_float());
76   EXPECT_EQ(pod->which(), PodUnion::Tag::F_FLOAT);
77 
78   pod->set_f_double(1.9);
79   EXPECT_EQ(1.9, pod->get_f_double());
80   EXPECT_TRUE(pod->is_f_double());
81   EXPECT_EQ(pod->which(), PodUnion::Tag::F_DOUBLE);
82 
83   pod->set_f_bool(true);
84   EXPECT_TRUE(pod->get_f_bool());
85   pod->set_f_bool(false);
86   EXPECT_FALSE(pod->get_f_bool());
87   EXPECT_TRUE(pod->is_f_bool());
88   EXPECT_EQ(pod->which(), PodUnion::Tag::F_BOOL);
89 
90   pod->set_f_enum(AnEnum::SECOND);
91   EXPECT_EQ(AnEnum::SECOND, pod->get_f_enum());
92   EXPECT_TRUE(pod->is_f_enum());
93   EXPECT_EQ(pod->which(), PodUnion::Tag::F_ENUM);
94 }
95 
TEST(UnionTest,PodEquals)96 TEST(UnionTest, PodEquals) {
97   PodUnionPtr pod1(PodUnion::New());
98   PodUnionPtr pod2(PodUnion::New());
99 
100   pod1->set_f_int8(10);
101   pod2->set_f_int8(10);
102   EXPECT_TRUE(pod1.Equals(pod2));
103 
104   pod2->set_f_int8(11);
105   EXPECT_FALSE(pod1.Equals(pod2));
106 
107   pod2->set_f_int8_other(10);
108   EXPECT_FALSE(pod1.Equals(pod2));
109 }
110 
TEST(UnionTest,PodClone)111 TEST(UnionTest, PodClone) {
112   PodUnionPtr pod(PodUnion::New());
113   pod->set_f_int8(10);
114 
115   PodUnionPtr pod_clone = pod.Clone();
116   EXPECT_EQ(10, pod_clone->get_f_int8());
117   EXPECT_TRUE(pod_clone->is_f_int8());
118   EXPECT_EQ(pod_clone->which(), PodUnion::Tag::F_INT8);
119 }
120 
TEST(UnionTest,PodSerialization)121 TEST(UnionTest, PodSerialization) {
122   PodUnionPtr pod1(PodUnion::New());
123   pod1->set_f_int8(10);
124 
125   mojo::internal::SerializationContext context;
126   size_t size =
127       mojo::internal::PrepareToSerialize<PodUnionPtr>(pod1, false, &context);
128   EXPECT_EQ(16U, size);
129 
130   mojo::internal::FixedBufferForTesting buf(size);
131   internal::PodUnion_Data* data = nullptr;
132   mojo::internal::Serialize<PodUnionPtr>(pod1, &buf, &data, false, &context);
133 
134   PodUnionPtr pod2;
135   mojo::internal::Deserialize<PodUnionPtr>(data, &pod2, &context);
136 
137   EXPECT_EQ(10, pod2->get_f_int8());
138   EXPECT_TRUE(pod2->is_f_int8());
139   EXPECT_EQ(pod2->which(), PodUnion::Tag::F_INT8);
140 }
141 
TEST(UnionTest,EnumSerialization)142 TEST(UnionTest, EnumSerialization) {
143   PodUnionPtr pod1(PodUnion::New());
144   pod1->set_f_enum(AnEnum::SECOND);
145 
146   size_t size =
147       mojo::internal::PrepareToSerialize<PodUnionPtr>(pod1, false, nullptr);
148   EXPECT_EQ(16U, size);
149 
150   mojo::internal::FixedBufferForTesting buf(size);
151   internal::PodUnion_Data* data = nullptr;
152   mojo::internal::Serialize<PodUnionPtr>(pod1, &buf, &data, false, nullptr);
153 
154   PodUnionPtr pod2;
155   mojo::internal::Deserialize<PodUnionPtr>(data, &pod2, nullptr);
156 
157   EXPECT_EQ(AnEnum::SECOND, pod2->get_f_enum());
158   EXPECT_TRUE(pod2->is_f_enum());
159   EXPECT_EQ(pod2->which(), PodUnion::Tag::F_ENUM);
160 }
161 
TEST(UnionTest,PodValidation)162 TEST(UnionTest, PodValidation) {
163   PodUnionPtr pod(PodUnion::New());
164   pod->set_f_int8(10);
165 
166   size_t size =
167       mojo::internal::PrepareToSerialize<PodUnionPtr>(pod, false, nullptr);
168   EXPECT_EQ(16U, size);
169 
170   mojo::internal::FixedBufferForTesting buf(size);
171   internal::PodUnion_Data* data = nullptr;
172   mojo::internal::Serialize<PodUnionPtr>(pod, &buf, &data, false, nullptr);
173 
174   void* raw_buf = buf.Leak();
175   mojo::internal::ValidationContext validation_context(
176       data, static_cast<uint32_t>(size), 0);
177   EXPECT_TRUE(
178       internal::PodUnion_Data::Validate(raw_buf, &validation_context, false));
179   free(raw_buf);
180 }
181 
TEST(UnionTest,SerializeNotNull)182 TEST(UnionTest, SerializeNotNull) {
183   PodUnionPtr pod(PodUnion::New());
184   pod->set_f_int8(0);
185   size_t size =
186       mojo::internal::PrepareToSerialize<PodUnionPtr>(pod, false, nullptr);
187   mojo::internal::FixedBufferForTesting buf(size);
188   internal::PodUnion_Data* data = nullptr;
189   mojo::internal::Serialize<PodUnionPtr>(pod, &buf, &data, false, nullptr);
190   EXPECT_FALSE(data->is_null());
191 }
192 
TEST(UnionTest,SerializeIsNullInlined)193 TEST(UnionTest, SerializeIsNullInlined) {
194   PodUnionPtr pod;
195   size_t size =
196       mojo::internal::PrepareToSerialize<PodUnionPtr>(pod, false, nullptr);
197   EXPECT_EQ(16U, size);
198   mojo::internal::FixedBufferForTesting buf(size);
199   internal::PodUnion_Data* data = internal::PodUnion_Data::New(&buf);
200 
201   // Check that dirty output buffers are handled correctly by serialization.
202   data->size = 16U;
203   data->tag = PodUnion::Tag::F_UINT16;
204   data->data.f_f_int16 = 20;
205 
206   mojo::internal::Serialize<PodUnionPtr>(pod, &buf, &data, true, nullptr);
207   EXPECT_TRUE(data->is_null());
208 
209   PodUnionPtr pod2;
210   mojo::internal::Deserialize<PodUnionPtr>(data, &pod2, nullptr);
211   EXPECT_TRUE(pod2.is_null());
212 }
213 
TEST(UnionTest,SerializeIsNullNotInlined)214 TEST(UnionTest, SerializeIsNullNotInlined) {
215   PodUnionPtr pod;
216   size_t size =
217       mojo::internal::PrepareToSerialize<PodUnionPtr>(pod, false, nullptr);
218   EXPECT_EQ(16U, size);
219   mojo::internal::FixedBufferForTesting buf(size);
220   internal::PodUnion_Data* data = nullptr;
221   mojo::internal::Serialize<PodUnionPtr>(pod, &buf, &data, false, nullptr);
222   EXPECT_EQ(nullptr, data);
223 }
224 
TEST(UnionTest,NullValidation)225 TEST(UnionTest, NullValidation) {
226   void* buf = nullptr;
227   mojo::internal::ValidationContext validation_context(buf, 0, 0);
228   EXPECT_TRUE(internal::PodUnion_Data::Validate(
229       buf, &validation_context, false));
230 }
231 
TEST(UnionTest,OutOfAlignmentValidation)232 TEST(UnionTest, OutOfAlignmentValidation) {
233   size_t size = sizeof(internal::PodUnion_Data);
234   // Get an aligned object and shift the alignment.
235   mojo::internal::FixedBufferForTesting aligned_buf(size + 1);
236   void* raw_buf = aligned_buf.Leak();
237   char* buf = reinterpret_cast<char*>(raw_buf) + 1;
238 
239   internal::PodUnion_Data* data =
240       reinterpret_cast<internal::PodUnion_Data*>(buf);
241   mojo::internal::ValidationContext validation_context(
242       data, static_cast<uint32_t>(size), 0);
243   EXPECT_FALSE(internal::PodUnion_Data::Validate(
244       buf, &validation_context, false));
245   free(raw_buf);
246 }
247 
TEST(UnionTest,OOBValidation)248 TEST(UnionTest, OOBValidation) {
249   size_t size = sizeof(internal::PodUnion_Data) - 1;
250   mojo::internal::FixedBufferForTesting buf(size);
251   internal::PodUnion_Data* data = internal::PodUnion_Data::New(&buf);
252   mojo::internal::ValidationContext validation_context(
253       data, static_cast<uint32_t>(size), 0);
254   void* raw_buf = buf.Leak();
255   EXPECT_FALSE(
256       internal::PodUnion_Data::Validate(raw_buf, &validation_context, false));
257   free(raw_buf);
258 }
259 
TEST(UnionTest,UnknownTagValidation)260 TEST(UnionTest, UnknownTagValidation) {
261   size_t size = sizeof(internal::PodUnion_Data);
262   mojo::internal::FixedBufferForTesting buf(size);
263   internal::PodUnion_Data* data = internal::PodUnion_Data::New(&buf);
264   data->tag = static_cast<internal::PodUnion_Data::PodUnion_Tag>(0xFFFFFF);
265   mojo::internal::ValidationContext validation_context(
266       data, static_cast<uint32_t>(size), 0);
267   void* raw_buf = buf.Leak();
268   EXPECT_FALSE(
269       internal::PodUnion_Data::Validate(raw_buf, &validation_context, false));
270   free(raw_buf);
271 }
272 
TEST(UnionTest,UnknownEnumValueValidation)273 TEST(UnionTest, UnknownEnumValueValidation) {
274   PodUnionPtr pod(PodUnion::New());
275   pod->set_f_enum(static_cast<AnEnum>(0xFFFF));
276 
277   size_t size =
278       mojo::internal::PrepareToSerialize<PodUnionPtr>(pod, false, nullptr);
279   EXPECT_EQ(16U, size);
280 
281   mojo::internal::FixedBufferForTesting buf(size);
282   internal::PodUnion_Data* data = nullptr;
283   mojo::internal::Serialize<PodUnionPtr>(pod, &buf, &data, false, nullptr);
284 
285   void* raw_buf = buf.Leak();
286   mojo::internal::ValidationContext validation_context(
287       data, static_cast<uint32_t>(size), 0);
288   EXPECT_FALSE(
289       internal::PodUnion_Data::Validate(raw_buf, &validation_context, false));
290   free(raw_buf);
291 }
292 
TEST(UnionTest,UnknownExtensibleEnumValueValidation)293 TEST(UnionTest, UnknownExtensibleEnumValueValidation) {
294   PodUnionPtr pod(PodUnion::New());
295   pod->set_f_extensible_enum(static_cast<AnExtensibleEnum>(0xFFFF));
296 
297   size_t size =
298       mojo::internal::PrepareToSerialize<PodUnionPtr>(pod, false, nullptr);
299   EXPECT_EQ(16U, size);
300 
301   mojo::internal::FixedBufferForTesting buf(size);
302   internal::PodUnion_Data* data = nullptr;
303   mojo::internal::Serialize<PodUnionPtr>(pod, &buf, &data, false, nullptr);
304 
305   void* raw_buf = buf.Leak();
306   mojo::internal::ValidationContext validation_context(
307       data, static_cast<uint32_t>(size), 0);
308   EXPECT_TRUE(
309       internal::PodUnion_Data::Validate(raw_buf, &validation_context, false));
310   free(raw_buf);
311 }
312 
TEST(UnionTest,StringGetterSetter)313 TEST(UnionTest, StringGetterSetter) {
314   ObjectUnionPtr pod(ObjectUnion::New());
315 
316   String hello("hello world");
317   pod->set_f_string(hello);
318   EXPECT_EQ(hello, pod->get_f_string());
319   EXPECT_TRUE(pod->is_f_string());
320   EXPECT_EQ(pod->which(), ObjectUnion::Tag::F_STRING);
321 }
322 
TEST(UnionTest,StringEquals)323 TEST(UnionTest, StringEquals) {
324   ObjectUnionPtr pod1(ObjectUnion::New());
325   ObjectUnionPtr pod2(ObjectUnion::New());
326 
327   pod1->set_f_string("hello world");
328   pod2->set_f_string("hello world");
329   EXPECT_TRUE(pod1.Equals(pod2));
330 
331   pod2->set_f_string("hello universe");
332   EXPECT_FALSE(pod1.Equals(pod2));
333 }
334 
TEST(UnionTest,StringClone)335 TEST(UnionTest, StringClone) {
336   ObjectUnionPtr pod(ObjectUnion::New());
337 
338   String hello("hello world");
339   pod->set_f_string(hello);
340   ObjectUnionPtr pod_clone = pod.Clone();
341   EXPECT_EQ(hello, pod_clone->get_f_string());
342   EXPECT_TRUE(pod_clone->is_f_string());
343   EXPECT_EQ(pod_clone->which(), ObjectUnion::Tag::F_STRING);
344 }
345 
TEST(UnionTest,StringSerialization)346 TEST(UnionTest, StringSerialization) {
347   ObjectUnionPtr pod1(ObjectUnion::New());
348 
349   String hello("hello world");
350   pod1->set_f_string(hello);
351 
352   size_t size =
353       mojo::internal::PrepareToSerialize<ObjectUnionPtr>(pod1, false, nullptr);
354   mojo::internal::FixedBufferForTesting buf(size);
355   internal::ObjectUnion_Data* data = nullptr;
356   mojo::internal::Serialize<ObjectUnionPtr>(pod1, &buf, &data, false, nullptr);
357 
358   ObjectUnionPtr pod2;
359   mojo::internal::Deserialize<ObjectUnionPtr>(data, &pod2, nullptr);
360   EXPECT_EQ(hello, pod2->get_f_string());
361   EXPECT_TRUE(pod2->is_f_string());
362   EXPECT_EQ(pod2->which(), ObjectUnion::Tag::F_STRING);
363 }
364 
TEST(UnionTest,NullStringValidation)365 TEST(UnionTest, NullStringValidation) {
366   size_t size = sizeof(internal::ObjectUnion_Data);
367   mojo::internal::FixedBufferForTesting buf(size);
368   internal::ObjectUnion_Data* data = internal::ObjectUnion_Data::New(&buf);
369   data->tag = internal::ObjectUnion_Data::ObjectUnion_Tag::F_STRING;
370   data->data.unknown = 0x0;
371   mojo::internal::ValidationContext validation_context(
372       data, static_cast<uint32_t>(size), 0);
373   void* raw_buf = buf.Leak();
374   EXPECT_FALSE(internal::ObjectUnion_Data::Validate(
375       raw_buf, &validation_context, false));
376   free(raw_buf);
377 }
378 
TEST(UnionTest,StringPointerOverflowValidation)379 TEST(UnionTest, StringPointerOverflowValidation) {
380   size_t size = sizeof(internal::ObjectUnion_Data);
381   mojo::internal::FixedBufferForTesting buf(size);
382   internal::ObjectUnion_Data* data = internal::ObjectUnion_Data::New(&buf);
383   data->tag = internal::ObjectUnion_Data::ObjectUnion_Tag::F_STRING;
384   data->data.unknown = 0xFFFFFFFFFFFFFFFF;
385   mojo::internal::ValidationContext validation_context(
386       data, static_cast<uint32_t>(size), 0);
387   void* raw_buf = buf.Leak();
388   EXPECT_FALSE(internal::ObjectUnion_Data::Validate(
389       raw_buf, &validation_context, false));
390   free(raw_buf);
391 }
392 
TEST(UnionTest,StringValidateOOB)393 TEST(UnionTest, StringValidateOOB) {
394   size_t size = 32;
395   mojo::internal::FixedBufferForTesting buf(size);
396   internal::ObjectUnion_Data* data = internal::ObjectUnion_Data::New(&buf);
397   data->tag = internal::ObjectUnion_Data::ObjectUnion_Tag::F_STRING;
398 
399   data->data.f_f_string.offset = 8;
400   char* ptr = reinterpret_cast<char*>(&data->data.f_f_string);
401   mojo::internal::ArrayHeader* array_header =
402       reinterpret_cast<mojo::internal::ArrayHeader*>(ptr + *ptr);
403   array_header->num_bytes = 20;  // This should go out of bounds.
404   array_header->num_elements = 20;
405   mojo::internal::ValidationContext validation_context(data, 32, 0);
406   void* raw_buf = buf.Leak();
407   EXPECT_FALSE(internal::ObjectUnion_Data::Validate(
408       raw_buf, &validation_context, false));
409   free(raw_buf);
410 }
411 
412 // TODO(azani): Move back in array_unittest.cc when possible.
413 // Array tests
TEST(UnionTest,PodUnionInArray)414 TEST(UnionTest, PodUnionInArray) {
415   SmallStructPtr small_struct(SmallStruct::New());
416   small_struct->pod_union_array.emplace(2);
417   small_struct->pod_union_array.value()[0] = PodUnion::New();
418   small_struct->pod_union_array.value()[1] = PodUnion::New();
419 
420   small_struct->pod_union_array.value()[0]->set_f_int8(10);
421   small_struct->pod_union_array.value()[1]->set_f_int16(12);
422 
423   EXPECT_EQ(10, small_struct->pod_union_array.value()[0]->get_f_int8());
424   EXPECT_EQ(12, small_struct->pod_union_array.value()[1]->get_f_int16());
425 }
426 
TEST(UnionTest,PodUnionInArraySerialization)427 TEST(UnionTest, PodUnionInArraySerialization) {
428   Array<PodUnionPtr> array(2);
429   array[0] = PodUnion::New();
430   array[1] = PodUnion::New();
431 
432   array[0]->set_f_int8(10);
433   array[1]->set_f_int16(12);
434   EXPECT_EQ(2U, array.size());
435 
436   size_t size =
437       mojo::internal::PrepareToSerialize<Array<PodUnionPtr>>(array, nullptr);
438   EXPECT_EQ(40U, size);
439 
440   mojo::internal::FixedBufferForTesting buf(size);
441   mojo::internal::Array_Data<internal::PodUnion_Data>* data;
442   mojo::internal::ContainerValidateParams validate_params(0, false, nullptr);
443   mojo::internal::Serialize<Array<PodUnionPtr>>(array, &buf, &data,
444                                                 &validate_params, nullptr);
445 
446   Array<PodUnionPtr> array2;
447   mojo::internal::Deserialize<Array<PodUnionPtr>>(data, &array2, nullptr);
448 
449   EXPECT_EQ(2U, array2.size());
450 
451   EXPECT_EQ(10, array2[0]->get_f_int8());
452   EXPECT_EQ(12, array2[1]->get_f_int16());
453 }
454 
TEST(UnionTest,PodUnionInArraySerializationWithNull)455 TEST(UnionTest, PodUnionInArraySerializationWithNull) {
456   Array<PodUnionPtr> array(2);
457   array[0] = PodUnion::New();
458 
459   array[0]->set_f_int8(10);
460   EXPECT_EQ(2U, array.size());
461 
462   size_t size =
463       mojo::internal::PrepareToSerialize<Array<PodUnionPtr>>(array, nullptr);
464   EXPECT_EQ(40U, size);
465 
466   mojo::internal::FixedBufferForTesting buf(size);
467   mojo::internal::Array_Data<internal::PodUnion_Data>* data;
468   mojo::internal::ContainerValidateParams validate_params(0, true, nullptr);
469   mojo::internal::Serialize<Array<PodUnionPtr>>(array, &buf, &data,
470                                                 &validate_params, nullptr);
471 
472   Array<PodUnionPtr> array2;
473   mojo::internal::Deserialize<Array<PodUnionPtr>>(data, &array2, nullptr);
474 
475   EXPECT_EQ(2U, array2.size());
476 
477   EXPECT_EQ(10, array2[0]->get_f_int8());
478   EXPECT_TRUE(array2[1].is_null());
479 }
480 
TEST(UnionTest,ObjectUnionInArraySerialization)481 TEST(UnionTest, ObjectUnionInArraySerialization) {
482   Array<ObjectUnionPtr> array(2);
483   array[0] = ObjectUnion::New();
484   array[1] = ObjectUnion::New();
485 
486   array[0]->set_f_string("hello");
487   array[1]->set_f_string("world");
488   EXPECT_EQ(2U, array.size());
489 
490   size_t size =
491       mojo::internal::PrepareToSerialize<Array<ObjectUnionPtr>>(array, nullptr);
492   EXPECT_EQ(72U, size);
493 
494   mojo::internal::FixedBufferForTesting buf(size);
495 
496   mojo::internal::Array_Data<internal::ObjectUnion_Data>* data;
497   mojo::internal::ContainerValidateParams validate_params(0, false, nullptr);
498   mojo::internal::Serialize<Array<ObjectUnionPtr>>(array, &buf, &data,
499                                                    &validate_params, nullptr);
500 
501   std::vector<char> new_buf;
502   new_buf.resize(size);
503 
504   void* raw_buf = buf.Leak();
505   memcpy(new_buf.data(), raw_buf, size);
506   free(raw_buf);
507 
508   data =
509       reinterpret_cast<mojo::internal::Array_Data<internal::ObjectUnion_Data>*>(
510           new_buf.data());
511   mojo::internal::ValidationContext validation_context(
512       data, static_cast<uint32_t>(size), 0);
513   ASSERT_TRUE(mojo::internal::Array_Data<internal::ObjectUnion_Data>::Validate(
514       data, &validation_context, &validate_params));
515 
516   Array<ObjectUnionPtr> array2;
517   mojo::internal::Deserialize<Array<ObjectUnionPtr>>(data, &array2, nullptr);
518 
519   EXPECT_EQ(2U, array2.size());
520 
521   EXPECT_EQ(String("hello"), array2[0]->get_f_string());
522   EXPECT_EQ(String("world"), array2[1]->get_f_string());
523 }
524 
525 // TODO(azani): Move back in struct_unittest.cc when possible.
526 // Struct tests
TEST(UnionTest,Clone_Union)527 TEST(UnionTest, Clone_Union) {
528   SmallStructPtr small_struct(SmallStruct::New());
529   small_struct->pod_union = PodUnion::New();
530   small_struct->pod_union->set_f_int8(10);
531 
532   SmallStructPtr clone = small_struct.Clone();
533   EXPECT_EQ(10, clone->pod_union->get_f_int8());
534 }
535 
536 // Serialization test of a struct with a union of plain old data.
TEST(UnionTest,Serialization_UnionOfPods)537 TEST(UnionTest, Serialization_UnionOfPods) {
538   SmallStructPtr small_struct(SmallStruct::New());
539   small_struct->pod_union = PodUnion::New();
540   small_struct->pod_union->set_f_int32(10);
541 
542   mojo::internal::SerializationContext context;
543   size_t size = mojo::internal::PrepareToSerialize<SmallStructPtr>(small_struct,
544                                                                    &context);
545 
546   mojo::internal::FixedBufferForTesting buf(size);
547   internal::SmallStruct_Data* data = nullptr;
548   mojo::internal::Serialize<SmallStructPtr>(small_struct, &buf, &data,
549                                             &context);
550 
551   SmallStructPtr deserialized;
552   mojo::internal::Deserialize<SmallStructPtr>(data, &deserialized, &context);
553 
554   EXPECT_EQ(10, deserialized->pod_union->get_f_int32());
555 }
556 
557 // Serialization test of a struct with a union of structs.
TEST(UnionTest,Serialization_UnionOfObjects)558 TEST(UnionTest, Serialization_UnionOfObjects) {
559   SmallObjStructPtr obj_struct(SmallObjStruct::New());
560   obj_struct->obj_union = ObjectUnion::New();
561   String hello("hello world");
562   obj_struct->obj_union->set_f_string(hello);
563 
564   size_t size = mojo::internal::PrepareToSerialize<SmallObjStructPtr>(
565       obj_struct, nullptr);
566 
567   mojo::internal::FixedBufferForTesting buf(size);
568   internal::SmallObjStruct_Data* data = nullptr;
569   mojo::internal::Serialize<SmallObjStructPtr>(obj_struct, &buf, &data,
570                                                nullptr);
571 
572   SmallObjStructPtr deserialized;
573   mojo::internal::Deserialize<SmallObjStructPtr>(data, &deserialized, nullptr);
574 
575   EXPECT_EQ(hello, deserialized->obj_union->get_f_string());
576 }
577 
578 // Validation test of a struct with a union.
TEST(UnionTest,Validation_UnionsInStruct)579 TEST(UnionTest, Validation_UnionsInStruct) {
580   SmallStructPtr small_struct(SmallStruct::New());
581   small_struct->pod_union = PodUnion::New();
582   small_struct->pod_union->set_f_int32(10);
583 
584   mojo::internal::SerializationContext context;
585   size_t size = mojo::internal::PrepareToSerialize<SmallStructPtr>(small_struct,
586                                                                    &context);
587 
588   mojo::internal::FixedBufferForTesting buf(size);
589   internal::SmallStruct_Data* data = nullptr;
590   mojo::internal::Serialize<SmallStructPtr>(small_struct, &buf, &data,
591                                             &context);
592 
593 
594   void* raw_buf = buf.Leak();
595   mojo::internal::ValidationContext validation_context(
596       data, static_cast<uint32_t>(size), 0);
597   EXPECT_TRUE(internal::SmallStruct_Data::Validate(
598       raw_buf, &validation_context));
599   free(raw_buf);
600 }
601 
602 // Validation test of a struct union fails due to unknown union tag.
TEST(UnionTest,Validation_PodUnionInStruct_Failure)603 TEST(UnionTest, Validation_PodUnionInStruct_Failure) {
604   SmallStructPtr small_struct(SmallStruct::New());
605   small_struct->pod_union = PodUnion::New();
606   small_struct->pod_union->set_f_int32(10);
607 
608   mojo::internal::SerializationContext context;
609   size_t size = mojo::internal::PrepareToSerialize<SmallStructPtr>(small_struct,
610                                                                    &context);
611 
612   mojo::internal::FixedBufferForTesting buf(size);
613   internal::SmallStruct_Data* data = nullptr;
614   mojo::internal::Serialize<SmallStructPtr>(small_struct, &buf, &data,
615                                             &context);
616   data->pod_union.tag = static_cast<internal::PodUnion_Data::PodUnion_Tag>(100);
617 
618   void* raw_buf = buf.Leak();
619   mojo::internal::ValidationContext validation_context(
620       data, static_cast<uint32_t>(size), 0);
621   EXPECT_FALSE(internal::SmallStruct_Data::Validate(
622       raw_buf, &validation_context));
623   free(raw_buf);
624 }
625 
626 // Validation fails due to non-nullable null union in struct.
TEST(UnionTest,Validation_NullUnion_Failure)627 TEST(UnionTest, Validation_NullUnion_Failure) {
628   SmallStructNonNullableUnionPtr small_struct(
629       SmallStructNonNullableUnion::New());
630 
631   size_t size =
632       mojo::internal::PrepareToSerialize<SmallStructNonNullableUnionPtr>(
633           small_struct, nullptr);
634 
635   mojo::internal::FixedBufferForTesting buf(size);
636   internal::SmallStructNonNullableUnion_Data* data =
637       internal::SmallStructNonNullableUnion_Data::New(&buf);
638 
639   void* raw_buf = buf.Leak();
640   mojo::internal::ValidationContext validation_context(
641       data, static_cast<uint32_t>(size), 0);
642   EXPECT_FALSE(internal::SmallStructNonNullableUnion_Data::Validate(
643       raw_buf, &validation_context));
644   free(raw_buf);
645 }
646 
647 // Validation passes with nullable null union.
TEST(UnionTest,Validation_NullableUnion)648 TEST(UnionTest, Validation_NullableUnion) {
649   SmallStructPtr small_struct(SmallStruct::New());
650 
651   mojo::internal::SerializationContext context;
652   size_t size = mojo::internal::PrepareToSerialize<SmallStructPtr>(small_struct,
653                                                                    &context);
654 
655   mojo::internal::FixedBufferForTesting buf(size);
656   internal::SmallStruct_Data* data = nullptr;
657   mojo::internal::Serialize<SmallStructPtr>(small_struct, &buf, &data,
658                                             &context);
659 
660   void* raw_buf = buf.Leak();
661   mojo::internal::ValidationContext validation_context(
662       data, static_cast<uint32_t>(size), 0);
663   EXPECT_TRUE(internal::SmallStruct_Data::Validate(
664       raw_buf, &validation_context));
665   free(raw_buf);
666 }
667 
668 // TODO(azani): Move back in map_unittest.cc when possible.
669 // Map Tests
TEST(UnionTest,PodUnionInMap)670 TEST(UnionTest, PodUnionInMap) {
671   SmallStructPtr small_struct(SmallStruct::New());
672   small_struct->pod_union_map.emplace();
673   small_struct->pod_union_map.value()["one"] = PodUnion::New();
674   small_struct->pod_union_map.value()["two"] = PodUnion::New();
675 
676   small_struct->pod_union_map.value()["one"]->set_f_int8(8);
677   small_struct->pod_union_map.value()["two"]->set_f_int16(16);
678 
679   EXPECT_EQ(8, small_struct->pod_union_map.value()["one"]->get_f_int8());
680   EXPECT_EQ(16, small_struct->pod_union_map.value()["two"]->get_f_int16());
681 }
682 
TEST(UnionTest,PodUnionInMapSerialization)683 TEST(UnionTest, PodUnionInMapSerialization) {
684   Map<String, PodUnionPtr> map;
685   map.insert("one", PodUnion::New());
686   map.insert("two", PodUnion::New());
687 
688   map["one"]->set_f_int8(8);
689   map["two"]->set_f_int16(16);
690 
691   mojo::internal::SerializationContext context;
692   size_t size = mojo::internal::PrepareToSerialize<Map<String, PodUnionPtr>>(
693       map, &context);
694   EXPECT_EQ(120U, size);
695 
696   mojo::internal::FixedBufferForTesting buf(size);
697   typename mojo::internal::MojomTypeTraits<Map<String, PodUnionPtr>>::Data*
698       data;
699   mojo::internal::ContainerValidateParams validate_params(
700       new mojo::internal::ContainerValidateParams(0, false, nullptr),
701       new mojo::internal::ContainerValidateParams(0, false, nullptr));
702   mojo::internal::Serialize<Map<String, PodUnionPtr>>(
703       map, &buf, &data, &validate_params, &context);
704 
705   Map<String, PodUnionPtr> map2;
706   mojo::internal::Deserialize<Map<String, PodUnionPtr>>(data, &map2, &context);
707 
708   EXPECT_EQ(8, map2["one"]->get_f_int8());
709   EXPECT_EQ(16, map2["two"]->get_f_int16());
710 }
711 
TEST(UnionTest,PodUnionInMapSerializationWithNull)712 TEST(UnionTest, PodUnionInMapSerializationWithNull) {
713   Map<String, PodUnionPtr> map;
714   map.insert("one", PodUnion::New());
715   map.insert("two", nullptr);
716 
717   map["one"]->set_f_int8(8);
718 
719   mojo::internal::SerializationContext context;
720   size_t size = mojo::internal::PrepareToSerialize<Map<String, PodUnionPtr>>(
721       map, &context);
722   EXPECT_EQ(120U, size);
723 
724   mojo::internal::FixedBufferForTesting buf(size);
725   typename mojo::internal::MojomTypeTraits<Map<String, PodUnionPtr>>::Data*
726       data;
727   mojo::internal::ContainerValidateParams validate_params(
728       new mojo::internal::ContainerValidateParams(0, false, nullptr),
729       new mojo::internal::ContainerValidateParams(0, true, nullptr));
730   mojo::internal::Serialize<Map<String, PodUnionPtr>>(
731       map, &buf, &data, &validate_params, &context);
732 
733   Map<String, PodUnionPtr> map2;
734   mojo::internal::Deserialize<Map<String, PodUnionPtr>>(data, &map2, &context);
735 
736   EXPECT_EQ(8, map2["one"]->get_f_int8());
737   EXPECT_TRUE(map2["two"].is_null());
738 }
739 
TEST(UnionTest,StructInUnionGetterSetterPasser)740 TEST(UnionTest, StructInUnionGetterSetterPasser) {
741   DummyStructPtr dummy(DummyStruct::New());
742   dummy->f_int8 = 8;
743 
744   ObjectUnionPtr obj(ObjectUnion::New());
745   obj->set_f_dummy(std::move(dummy));
746 
747   EXPECT_EQ(8, obj->get_f_dummy()->f_int8);
748 }
749 
TEST(UnionTest,StructInUnionSerialization)750 TEST(UnionTest, StructInUnionSerialization) {
751   DummyStructPtr dummy(DummyStruct::New());
752   dummy->f_int8 = 8;
753 
754   ObjectUnionPtr obj(ObjectUnion::New());
755   obj->set_f_dummy(std::move(dummy));
756 
757   size_t size =
758       mojo::internal::PrepareToSerialize<ObjectUnionPtr>(obj, false, nullptr);
759   EXPECT_EQ(32U, size);
760 
761   mojo::internal::FixedBufferForTesting buf(size);
762   internal::ObjectUnion_Data* data = nullptr;
763   mojo::internal::Serialize<ObjectUnionPtr>(obj, &buf, &data, false, nullptr);
764 
765   ObjectUnionPtr obj2;
766   mojo::internal::Deserialize<ObjectUnionPtr>(data, &obj2, nullptr);
767   EXPECT_EQ(8, obj2->get_f_dummy()->f_int8);
768 }
769 
TEST(UnionTest,StructInUnionValidation)770 TEST(UnionTest, StructInUnionValidation) {
771   DummyStructPtr dummy(DummyStruct::New());
772   dummy->f_int8 = 8;
773 
774   ObjectUnionPtr obj(ObjectUnion::New());
775   obj->set_f_dummy(std::move(dummy));
776 
777   size_t size =
778       mojo::internal::PrepareToSerialize<ObjectUnionPtr>(obj, false, nullptr);
779 
780   mojo::internal::FixedBufferForTesting buf(size);
781   internal::ObjectUnion_Data* data = nullptr;
782   mojo::internal::Serialize<ObjectUnionPtr>(obj, &buf, &data, false, nullptr);
783 
784   void* raw_buf = buf.Leak();
785   mojo::internal::ValidationContext validation_context(
786       data, static_cast<uint32_t>(size), 0);
787   EXPECT_TRUE(internal::ObjectUnion_Data::Validate(
788       raw_buf, &validation_context, false));
789   free(raw_buf);
790 }
791 
TEST(UnionTest,StructInUnionValidationNonNullable)792 TEST(UnionTest, StructInUnionValidationNonNullable) {
793   mojo::internal::SerializationWarningObserverForTesting suppress_warning;
794 
795   DummyStructPtr dummy(nullptr);
796 
797   ObjectUnionPtr obj(ObjectUnion::New());
798   obj->set_f_dummy(std::move(dummy));
799 
800   size_t size =
801       mojo::internal::PrepareToSerialize<ObjectUnionPtr>(obj, false, nullptr);
802 
803   mojo::internal::FixedBufferForTesting buf(size);
804   internal::ObjectUnion_Data* data = nullptr;
805   mojo::internal::Serialize<ObjectUnionPtr>(obj, &buf, &data, false, nullptr);
806 
807   void* raw_buf = buf.Leak();
808   mojo::internal::ValidationContext validation_context(
809       data, static_cast<uint32_t>(size), 0);
810   EXPECT_FALSE(internal::ObjectUnion_Data::Validate(
811       raw_buf, &validation_context, false));
812   free(raw_buf);
813 }
814 
TEST(UnionTest,StructInUnionValidationNullable)815 TEST(UnionTest, StructInUnionValidationNullable) {
816   DummyStructPtr dummy(nullptr);
817 
818   ObjectUnionPtr obj(ObjectUnion::New());
819   obj->set_f_nullable(std::move(dummy));
820 
821   size_t size =
822       mojo::internal::PrepareToSerialize<ObjectUnionPtr>(obj, false, nullptr);
823 
824   mojo::internal::FixedBufferForTesting buf(size);
825   internal::ObjectUnion_Data* data = nullptr;
826   mojo::internal::Serialize<ObjectUnionPtr>(obj, &buf, &data, false, nullptr);
827 
828   void* raw_buf = buf.Leak();
829   mojo::internal::ValidationContext validation_context(
830       data, static_cast<uint32_t>(size), 0);
831   EXPECT_TRUE(internal::ObjectUnion_Data::Validate(
832       raw_buf, &validation_context, false));
833   free(raw_buf);
834 }
835 
TEST(UnionTest,ArrayInUnionGetterSetter)836 TEST(UnionTest, ArrayInUnionGetterSetter) {
837   Array<int8_t> array(2);
838   array[0] = 8;
839   array[1] = 9;
840 
841   ObjectUnionPtr obj(ObjectUnion::New());
842   obj->set_f_array_int8(std::move(array));
843 
844   EXPECT_EQ(8, obj->get_f_array_int8()[0]);
845   EXPECT_EQ(9, obj->get_f_array_int8()[1]);
846 }
847 
TEST(UnionTest,ArrayInUnionSerialization)848 TEST(UnionTest, ArrayInUnionSerialization) {
849   Array<int8_t> array(2);
850   array[0] = 8;
851   array[1] = 9;
852 
853   ObjectUnionPtr obj(ObjectUnion::New());
854   obj->set_f_array_int8(std::move(array));
855 
856   size_t size =
857       mojo::internal::PrepareToSerialize<ObjectUnionPtr>(obj, false, nullptr);
858   EXPECT_EQ(32U, size);
859 
860   mojo::internal::FixedBufferForTesting buf(size);
861   internal::ObjectUnion_Data* data = nullptr;
862   mojo::internal::Serialize<ObjectUnionPtr>(obj, &buf, &data, false, nullptr);
863 
864   ObjectUnionPtr obj2;
865   mojo::internal::Deserialize<ObjectUnionPtr>(data, &obj2, nullptr);
866 
867   EXPECT_EQ(8, obj2->get_f_array_int8()[0]);
868   EXPECT_EQ(9, obj2->get_f_array_int8()[1]);
869 }
870 
TEST(UnionTest,ArrayInUnionValidation)871 TEST(UnionTest, ArrayInUnionValidation) {
872   Array<int8_t> array(2);
873   array[0] = 8;
874   array[1] = 9;
875 
876   ObjectUnionPtr obj(ObjectUnion::New());
877   obj->set_f_array_int8(std::move(array));
878 
879   size_t size =
880       mojo::internal::PrepareToSerialize<ObjectUnionPtr>(obj, false, nullptr);
881   mojo::internal::FixedBufferForTesting buf(size);
882   internal::ObjectUnion_Data* data = nullptr;
883   mojo::internal::Serialize<ObjectUnionPtr>(obj, &buf, &data, false, nullptr);
884 
885   void* raw_buf = buf.Leak();
886   mojo::internal::ValidationContext validation_context(
887       data, static_cast<uint32_t>(size), 0);
888 
889   EXPECT_TRUE(internal::ObjectUnion_Data::Validate(
890       raw_buf, &validation_context, false));
891   free(raw_buf);
892 }
893 
TEST(UnionTest,MapInUnionGetterSetter)894 TEST(UnionTest, MapInUnionGetterSetter) {
895   std::unordered_map<std::string, int8_t> map;
896   map.insert({"one", 1});
897   map.insert({"two", 2});
898 
899   ObjectUnionPtr obj(ObjectUnion::New());
900   obj->set_f_map_int8(std::move(map));
901 
902   EXPECT_EQ(1, obj->get_f_map_int8()["one"]);
903   EXPECT_EQ(2, obj->get_f_map_int8()["two"]);
904 }
905 
TEST(UnionTest,MapInUnionSerialization)906 TEST(UnionTest, MapInUnionSerialization) {
907   std::unordered_map<std::string, int8_t> map;
908   map.insert({"one", 1});
909   map.insert({"two", 2});
910 
911   ObjectUnionPtr obj(ObjectUnion::New());
912   obj->set_f_map_int8(std::move(map));
913 
914   mojo::internal::SerializationContext context;
915   size_t size =
916       mojo::internal::PrepareToSerialize<ObjectUnionPtr>(obj, false, &context);
917   EXPECT_EQ(112U, size);
918 
919   mojo::internal::FixedBufferForTesting buf(size);
920   internal::ObjectUnion_Data* data = nullptr;
921   mojo::internal::Serialize<ObjectUnionPtr>(obj, &buf, &data, false, &context);
922 
923   ObjectUnionPtr obj2;
924   mojo::internal::Deserialize<ObjectUnionPtr>(data, &obj2, &context);
925 
926   EXPECT_EQ(1, obj2->get_f_map_int8()["one"]);
927   EXPECT_EQ(2, obj2->get_f_map_int8()["two"]);
928 }
929 
TEST(UnionTest,MapInUnionValidation)930 TEST(UnionTest, MapInUnionValidation) {
931   std::unordered_map<std::string, int8_t> map;
932   map.insert({"one", 1});
933   map.insert({"two", 2});
934 
935   ObjectUnionPtr obj(ObjectUnion::New());
936   obj->set_f_map_int8(std::move(map));
937 
938   mojo::internal::SerializationContext context;
939   size_t size =
940       mojo::internal::PrepareToSerialize<ObjectUnionPtr>(obj, false, &context);
941   EXPECT_EQ(112U, size);
942 
943   mojo::internal::FixedBufferForTesting buf(size);
944   internal::ObjectUnion_Data* data = nullptr;
945   mojo::internal::Serialize<ObjectUnionPtr>(obj, &buf, &data, false, &context);
946 
947   void* raw_buf = buf.Leak();
948   mojo::internal::ValidationContext validation_context(
949       data, static_cast<uint32_t>(size), 0);
950 
951   EXPECT_TRUE(internal::ObjectUnion_Data::Validate(
952       raw_buf, &validation_context, false));
953   free(raw_buf);
954 }
955 
TEST(UnionTest,UnionInUnionGetterSetter)956 TEST(UnionTest, UnionInUnionGetterSetter) {
957   PodUnionPtr pod(PodUnion::New());
958   pod->set_f_int8(10);
959 
960   ObjectUnionPtr obj(ObjectUnion::New());
961   obj->set_f_pod_union(std::move(pod));
962 
963   EXPECT_EQ(10, obj->get_f_pod_union()->get_f_int8());
964 }
965 
TEST(UnionTest,UnionInUnionSerialization)966 TEST(UnionTest, UnionInUnionSerialization) {
967   PodUnionPtr pod(PodUnion::New());
968   pod->set_f_int8(10);
969 
970   ObjectUnionPtr obj(ObjectUnion::New());
971   obj->set_f_pod_union(std::move(pod));
972 
973   size_t size =
974       mojo::internal::PrepareToSerialize<ObjectUnionPtr>(obj, false, nullptr);
975   EXPECT_EQ(32U, size);
976 
977   mojo::internal::FixedBufferForTesting buf(size);
978   internal::ObjectUnion_Data* data = nullptr;
979   mojo::internal::Serialize<ObjectUnionPtr>(obj, &buf, &data, false, nullptr);
980 
981   ObjectUnionPtr obj2;
982   mojo::internal::Deserialize<ObjectUnionPtr>(data, &obj2, nullptr);
983   EXPECT_EQ(10, obj2->get_f_pod_union()->get_f_int8());
984 }
985 
TEST(UnionTest,UnionInUnionValidation)986 TEST(UnionTest, UnionInUnionValidation) {
987   PodUnionPtr pod(PodUnion::New());
988   pod->set_f_int8(10);
989 
990   ObjectUnionPtr obj(ObjectUnion::New());
991   obj->set_f_pod_union(std::move(pod));
992 
993   size_t size =
994       mojo::internal::PrepareToSerialize<ObjectUnionPtr>(obj, false, nullptr);
995   EXPECT_EQ(32U, size);
996 
997   mojo::internal::FixedBufferForTesting buf(size);
998   internal::ObjectUnion_Data* data = nullptr;
999   mojo::internal::Serialize<ObjectUnionPtr>(obj, &buf, &data, false, nullptr);
1000 
1001   void* raw_buf = buf.Leak();
1002   mojo::internal::ValidationContext validation_context(
1003       data, static_cast<uint32_t>(size), 0);
1004   EXPECT_TRUE(internal::ObjectUnion_Data::Validate(
1005       raw_buf, &validation_context, false));
1006   free(raw_buf);
1007 }
1008 
TEST(UnionTest,UnionInUnionValidationNonNullable)1009 TEST(UnionTest, UnionInUnionValidationNonNullable) {
1010   mojo::internal::SerializationWarningObserverForTesting suppress_warning;
1011 
1012   PodUnionPtr pod(nullptr);
1013 
1014   ObjectUnionPtr obj(ObjectUnion::New());
1015   obj->set_f_pod_union(std::move(pod));
1016 
1017   size_t size =
1018       mojo::internal::PrepareToSerialize<ObjectUnionPtr>(obj, false, nullptr);
1019 
1020   mojo::internal::FixedBufferForTesting buf(size);
1021   internal::ObjectUnion_Data* data = nullptr;
1022   mojo::internal::Serialize<ObjectUnionPtr>(obj, &buf, &data, false, nullptr);
1023 
1024   void* raw_buf = buf.Leak();
1025   mojo::internal::ValidationContext validation_context(
1026       data, static_cast<uint32_t>(size), 0);
1027   EXPECT_FALSE(internal::ObjectUnion_Data::Validate(
1028       raw_buf, &validation_context, false));
1029   free(raw_buf);
1030 }
1031 
TEST(UnionTest,HandleInUnionGetterSetter)1032 TEST(UnionTest, HandleInUnionGetterSetter) {
1033   ScopedMessagePipeHandle pipe0;
1034   ScopedMessagePipeHandle pipe1;
1035 
1036   CreateMessagePipe(nullptr, &pipe0, &pipe1);
1037 
1038   HandleUnionPtr handle(HandleUnion::New());
1039   handle->set_f_message_pipe(std::move(pipe1));
1040 
1041   std::string golden("hello world");
1042   WriteTextMessage(pipe0.get(), golden);
1043 
1044   std::string actual;
1045   ReadTextMessage(handle->get_f_message_pipe().get(), &actual);
1046 
1047   EXPECT_EQ(golden, actual);
1048 }
1049 
TEST(UnionTest,HandleInUnionSerialization)1050 TEST(UnionTest, HandleInUnionSerialization) {
1051   ScopedMessagePipeHandle pipe0;
1052   ScopedMessagePipeHandle pipe1;
1053 
1054   CreateMessagePipe(nullptr, &pipe0, &pipe1);
1055 
1056   HandleUnionPtr handle(HandleUnion::New());
1057   handle->set_f_message_pipe(std::move(pipe1));
1058 
1059   mojo::internal::SerializationContext context;
1060   size_t size = mojo::internal::PrepareToSerialize<HandleUnionPtr>(
1061       handle, false, &context);
1062   EXPECT_EQ(16U, size);
1063 
1064   mojo::internal::FixedBufferForTesting buf(size);
1065   internal::HandleUnion_Data* data = nullptr;
1066   mojo::internal::Serialize<HandleUnionPtr>(handle, &buf, &data, false,
1067                                             &context);
1068   EXPECT_EQ(1U, context.handles.size());
1069 
1070   HandleUnionPtr handle2(HandleUnion::New());
1071   mojo::internal::Deserialize<HandleUnionPtr>(data, &handle2, &context);
1072 
1073   std::string golden("hello world");
1074   WriteTextMessage(pipe0.get(), golden);
1075 
1076   std::string actual;
1077   ReadTextMessage(handle2->get_f_message_pipe().get(), &actual);
1078 
1079   EXPECT_EQ(golden, actual);
1080 }
1081 
TEST(UnionTest,HandleInUnionValidation)1082 TEST(UnionTest, HandleInUnionValidation) {
1083   ScopedMessagePipeHandle pipe0;
1084   ScopedMessagePipeHandle pipe1;
1085 
1086   CreateMessagePipe(nullptr, &pipe0, &pipe1);
1087 
1088   HandleUnionPtr handle(HandleUnion::New());
1089   handle->set_f_message_pipe(std::move(pipe1));
1090 
1091   mojo::internal::SerializationContext context;
1092   size_t size = mojo::internal::PrepareToSerialize<HandleUnionPtr>(
1093       handle, false, &context);
1094   EXPECT_EQ(16U, size);
1095 
1096   mojo::internal::FixedBufferForTesting buf(size);
1097   internal::HandleUnion_Data* data = nullptr;
1098   mojo::internal::Serialize<HandleUnionPtr>(handle, &buf, &data, false,
1099                                             &context);
1100 
1101   void* raw_buf = buf.Leak();
1102   mojo::internal::ValidationContext validation_context(
1103       data, static_cast<uint32_t>(size), 1);
1104   EXPECT_TRUE(internal::HandleUnion_Data::Validate(
1105       raw_buf, &validation_context, false));
1106   free(raw_buf);
1107 }
1108 
TEST(UnionTest,HandleInUnionValidationNull)1109 TEST(UnionTest, HandleInUnionValidationNull) {
1110   mojo::internal::SerializationWarningObserverForTesting suppress_warning;
1111 
1112   ScopedMessagePipeHandle pipe;
1113   HandleUnionPtr handle(HandleUnion::New());
1114   handle->set_f_message_pipe(std::move(pipe));
1115 
1116   mojo::internal::SerializationContext context;
1117   size_t size = mojo::internal::PrepareToSerialize<HandleUnionPtr>(
1118       handle, false, &context);
1119   EXPECT_EQ(16U, size);
1120 
1121   mojo::internal::FixedBufferForTesting buf(size);
1122   internal::HandleUnion_Data* data = nullptr;
1123   mojo::internal::Serialize<HandleUnionPtr>(handle, &buf, &data, false,
1124                                             &context);
1125 
1126   void* raw_buf = buf.Leak();
1127   mojo::internal::ValidationContext validation_context(
1128       data, static_cast<uint32_t>(size), 1);
1129   EXPECT_FALSE(internal::HandleUnion_Data::Validate(
1130       raw_buf, &validation_context, false));
1131   free(raw_buf);
1132 }
1133 
1134 class SmallCacheImpl : public SmallCache {
1135  public:
SmallCacheImpl(const base::Closure & closure)1136   explicit SmallCacheImpl(const base::Closure& closure)
1137       : int_value_(0), closure_(closure) {}
~SmallCacheImpl()1138   ~SmallCacheImpl() override {}
int_value() const1139   int64_t int_value() const { return int_value_; }
1140 
1141  private:
SetIntValue(int64_t int_value)1142   void SetIntValue(int64_t int_value) override {
1143     int_value_ = int_value;
1144     closure_.Run();
1145   }
GetIntValue(const GetIntValueCallback & callback)1146   void GetIntValue(const GetIntValueCallback& callback) override {
1147     callback.Run(int_value_);
1148   }
1149 
1150   int64_t int_value_;
1151   base::Closure closure_;
1152 };
1153 
TEST(UnionTest,InterfaceInUnion)1154 TEST(UnionTest, InterfaceInUnion) {
1155   base::MessageLoop message_loop;
1156   base::RunLoop run_loop;
1157   SmallCacheImpl impl(run_loop.QuitClosure());
1158   SmallCachePtr ptr;
1159   Binding<SmallCache> bindings(&impl, GetProxy(&ptr));
1160 
1161   HandleUnionPtr handle(HandleUnion::New());
1162   handle->set_f_small_cache(std::move(ptr));
1163 
1164   handle->get_f_small_cache()->SetIntValue(10);
1165   run_loop.Run();
1166   EXPECT_EQ(10, impl.int_value());
1167 }
1168 
TEST(UnionTest,InterfaceInUnionSerialization)1169 TEST(UnionTest, InterfaceInUnionSerialization) {
1170   base::MessageLoop message_loop;
1171   base::RunLoop run_loop;
1172   SmallCacheImpl impl(run_loop.QuitClosure());
1173   SmallCachePtr ptr;
1174   Binding<SmallCache> bindings(&impl, GetProxy(&ptr));
1175 
1176   mojo::internal::SerializationContext context;
1177   HandleUnionPtr handle(HandleUnion::New());
1178   handle->set_f_small_cache(std::move(ptr));
1179   size_t size = mojo::internal::PrepareToSerialize<HandleUnionPtr>(
1180       handle, false, &context);
1181   EXPECT_EQ(16U, size);
1182 
1183   mojo::internal::FixedBufferForTesting buf(size);
1184   internal::HandleUnion_Data* data = nullptr;
1185   mojo::internal::Serialize<HandleUnionPtr>(handle, &buf, &data, false,
1186                                             &context);
1187   EXPECT_EQ(1U, context.handles.size());
1188 
1189   HandleUnionPtr handle2(HandleUnion::New());
1190   mojo::internal::Deserialize<HandleUnionPtr>(data, &handle2, &context);
1191 
1192   handle2->get_f_small_cache()->SetIntValue(10);
1193   run_loop.Run();
1194   EXPECT_EQ(10, impl.int_value());
1195 }
1196 
1197 class UnionInterfaceImpl : public UnionInterface {
1198  public:
UnionInterfaceImpl()1199   UnionInterfaceImpl() {}
~UnionInterfaceImpl()1200   ~UnionInterfaceImpl() override {}
1201 
1202  private:
Echo(PodUnionPtr in,const EchoCallback & callback)1203   void Echo(PodUnionPtr in, const EchoCallback& callback) override {
1204     callback.Run(std::move(in));
1205   }
1206 };
1207 
ExpectInt16(int16_t value,PodUnionPtr out)1208 void ExpectInt16(int16_t value, PodUnionPtr out) {
1209   EXPECT_EQ(value, out->get_f_int16());
1210 }
1211 
TEST(UnionTest,UnionInInterface)1212 TEST(UnionTest, UnionInInterface) {
1213   base::MessageLoop message_loop;
1214   UnionInterfaceImpl impl;
1215   UnionInterfacePtr ptr;
1216   Binding<UnionInterface> bindings(&impl, GetProxy(&ptr));
1217 
1218   PodUnionPtr pod(PodUnion::New());
1219   pod->set_f_int16(16);
1220 
1221   ptr->Echo(std::move(pod), base::Bind(&ExpectInt16, 16));
1222   base::RunLoop().RunUntilIdle();
1223 }
1224 
1225 }  // namespace test
1226 }  // namespace mojo
1227