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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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. 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. 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. 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. 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. 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. 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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: 1136 explicit SmallCacheImpl(const base::Closure& closure) 1137 : int_value_(0), closure_(closure) {} 1138 ~SmallCacheImpl() override {} 1139 int64_t int_value() const { return int_value_; } 1140 1141 private: 1142 void SetIntValue(int64_t int_value) override { 1143 int_value_ = int_value; 1144 closure_.Run(); 1145 } 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 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 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: 1199 UnionInterfaceImpl() {} 1200 ~UnionInterfaceImpl() override {} 1201 1202 private: 1203 void Echo(PodUnionPtr in, const EchoCallback& callback) override { 1204 callback.Run(std::move(in)); 1205 } 1206 }; 1207 1208 void ExpectInt16(int16_t value, PodUnionPtr out) { 1209 EXPECT_EQ(value, out->get_f_int16()); 1210 } 1211 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