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