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