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