Home | History | Annotate | Download | only in tests
      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