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