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