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 <string.h>
      8 #include <utility>
      9 
     10 #include "mojo/public/cpp/bindings/lib/fixed_buffer.h"
     11 #include "mojo/public/cpp/system/message_pipe.h"
     12 #include "mojo/public/interfaces/bindings/tests/test_structs.mojom.h"
     13 #include "testing/gtest/include/gtest/gtest.h"
     14 
     15 namespace mojo {
     16 namespace test {
     17 namespace {
     18 
     19 RectPtr MakeRect(int32_t factor = 1) {
     20   RectPtr rect(Rect::New());
     21   rect->x = 1 * factor;
     22   rect->y = 2 * factor;
     23   rect->width = 10 * factor;
     24   rect->height = 20 * factor;
     25   return rect;
     26 }
     27 
     28 void CheckRect(const Rect& rect, int32_t factor = 1) {
     29   EXPECT_EQ(1 * factor, rect.x);
     30   EXPECT_EQ(2 * factor, rect.y);
     31   EXPECT_EQ(10 * factor, rect.width);
     32   EXPECT_EQ(20 * factor, rect.height);
     33 }
     34 
     35 MultiVersionStructPtr MakeMultiVersionStruct() {
     36   MultiVersionStructPtr output(MultiVersionStruct::New());
     37   output->f_int32 = 123;
     38   output->f_rect = MakeRect(5);
     39   output->f_string.emplace("hello");
     40   output->f_array.emplace(3);
     41   (*output->f_array)[0] = 10;
     42   (*output->f_array)[1] = 9;
     43   (*output->f_array)[2] = 8;
     44   MessagePipe pipe;
     45   output->f_message_pipe = std::move(pipe.handle0);
     46   output->f_int16 = 42;
     47 
     48   return output;
     49 }
     50 
     51 template <typename U, typename T>
     52 U SerializeAndDeserialize(T input) {
     53   using InputDataType = typename mojo::internal::MojomTypeTraits<T>::Data*;
     54   using OutputDataType = typename mojo::internal::MojomTypeTraits<U>::Data*;
     55 
     56   mojo::internal::SerializationContext context;
     57   size_t size = mojo::internal::PrepareToSerialize<T>(input, &context);
     58   mojo::internal::FixedBufferForTesting buf(size + 32);
     59   InputDataType data;
     60   mojo::internal::Serialize<T>(input, &buf, &data, &context);
     61 
     62   // Set the subsequent area to a special value, so that we can find out if we
     63   // mistakenly access the area.
     64   void* subsequent_area = buf.Allocate(32);
     65   memset(subsequent_area, 0xAA, 32);
     66 
     67   OutputDataType output_data = reinterpret_cast<OutputDataType>(data);
     68 
     69   U output;
     70   mojo::internal::Deserialize<U>(output_data, &output, &context);
     71   return std::move(output);
     72 }
     73 
     74 using StructTest = testing::Test;
     75 
     76 }  // namespace
     77 
     78 TEST_F(StructTest, Rect) {
     79   RectPtr rect;
     80   EXPECT_TRUE(rect.is_null());
     81   EXPECT_TRUE(!rect);
     82   EXPECT_FALSE(rect);
     83 
     84   rect = nullptr;
     85   EXPECT_TRUE(rect.is_null());
     86   EXPECT_TRUE(!rect);
     87   EXPECT_FALSE(rect);
     88 
     89   rect = MakeRect();
     90   EXPECT_FALSE(rect.is_null());
     91   EXPECT_FALSE(!rect);
     92   EXPECT_TRUE(rect);
     93 
     94   RectPtr null_rect = nullptr;
     95   EXPECT_TRUE(null_rect.is_null());
     96   EXPECT_TRUE(!null_rect);
     97   EXPECT_FALSE(null_rect);
     98 
     99   CheckRect(*rect);
    100 }
    101 
    102 TEST_F(StructTest, Clone) {
    103   NamedRegionPtr region;
    104 
    105   NamedRegionPtr clone_region = region.Clone();
    106   EXPECT_TRUE(clone_region.is_null());
    107 
    108   region = NamedRegion::New();
    109   clone_region = region.Clone();
    110   EXPECT_FALSE(clone_region->name);
    111   EXPECT_FALSE(clone_region->rects);
    112 
    113   region->name.emplace("hello world");
    114   clone_region = region.Clone();
    115   EXPECT_EQ(region->name, clone_region->name);
    116 
    117   region->rects.emplace(2);
    118   (*region->rects)[1] = MakeRect();
    119   clone_region = region.Clone();
    120   EXPECT_EQ(2u, clone_region->rects->size());
    121   EXPECT_TRUE((*clone_region->rects)[0].is_null());
    122   CheckRect(*(*clone_region->rects)[1]);
    123 
    124   // NoDefaultFieldValues contains handles, so Clone() is not available, but
    125   // NoDefaultFieldValuesPtr should still compile.
    126   NoDefaultFieldValuesPtr no_default_field_values(NoDefaultFieldValues::New());
    127   EXPECT_FALSE(no_default_field_values->f13.is_valid());
    128 }
    129 
    130 // Serialization test of a struct with no pointer or handle members.
    131 TEST_F(StructTest, Serialization_Basic) {
    132   RectPtr rect(MakeRect());
    133 
    134   size_t size = mojo::internal::PrepareToSerialize<RectPtr>(rect, nullptr);
    135   EXPECT_EQ(8U + 16U, size);
    136 
    137   mojo::internal::FixedBufferForTesting buf(size);
    138   internal::Rect_Data* data;
    139   mojo::internal::Serialize<RectPtr>(rect, &buf, &data, nullptr);
    140 
    141   RectPtr rect2;
    142   mojo::internal::Deserialize<RectPtr>(data, &rect2, nullptr);
    143 
    144   CheckRect(*rect2);
    145 }
    146 
    147 // Construction of a struct with struct pointers from null.
    148 TEST_F(StructTest, Construction_StructPointers) {
    149   RectPairPtr pair;
    150   EXPECT_TRUE(pair.is_null());
    151 
    152   pair = RectPair::New();
    153   EXPECT_FALSE(pair.is_null());
    154   EXPECT_TRUE(pair->first.is_null());
    155   EXPECT_TRUE(pair->first.is_null());
    156 
    157   pair = nullptr;
    158   EXPECT_TRUE(pair.is_null());
    159 }
    160 
    161 // Serialization test of a struct with struct pointers.
    162 TEST_F(StructTest, Serialization_StructPointers) {
    163   RectPairPtr pair(RectPair::New());
    164   pair->first = MakeRect();
    165   pair->second = MakeRect();
    166 
    167   size_t size = mojo::internal::PrepareToSerialize<RectPairPtr>(pair, nullptr);
    168   EXPECT_EQ(8U + 16U + 2 * (8U + 16U), size);
    169 
    170   mojo::internal::FixedBufferForTesting buf(size);
    171   internal::RectPair_Data* data;
    172   mojo::internal::Serialize<RectPairPtr>(pair, &buf, &data, nullptr);
    173 
    174   RectPairPtr pair2;
    175   mojo::internal::Deserialize<RectPairPtr>(data, &pair2, nullptr);
    176 
    177   CheckRect(*pair2->first);
    178   CheckRect(*pair2->second);
    179 }
    180 
    181 // Serialization test of a struct with an array member.
    182 TEST_F(StructTest, Serialization_ArrayPointers) {
    183   NamedRegionPtr region(NamedRegion::New());
    184   region->name.emplace("region");
    185   region->rects.emplace(4);
    186   for (size_t i = 0; i < region->rects->size(); ++i)
    187     (*region->rects)[i] = MakeRect(static_cast<int32_t>(i) + 1);
    188 
    189   size_t size =
    190       mojo::internal::PrepareToSerialize<NamedRegionPtr>(region, nullptr);
    191   EXPECT_EQ(8U +            // header
    192                 8U +        // name pointer
    193                 8U +        // rects pointer
    194                 8U +        // name header
    195                 8U +        // name payload (rounded up)
    196                 8U +        // rects header
    197                 4 * 8U +    // rects payload (four pointers)
    198                 4 * (8U +   // rect header
    199                      16U),  // rect payload (four ints)
    200             size);
    201 
    202   mojo::internal::FixedBufferForTesting buf(size);
    203   internal::NamedRegion_Data* data;
    204   mojo::internal::Serialize<NamedRegionPtr>(region, &buf, &data, nullptr);
    205 
    206   NamedRegionPtr region2;
    207   mojo::internal::Deserialize<NamedRegionPtr>(data, &region2, nullptr);
    208 
    209   EXPECT_EQ("region", *region2->name);
    210 
    211   EXPECT_EQ(4U, region2->rects->size());
    212   for (size_t i = 0; i < region2->rects->size(); ++i)
    213     CheckRect(*(*region2->rects)[i], static_cast<int32_t>(i) + 1);
    214 }
    215 
    216 // Serialization test of a struct with null array pointers.
    217 TEST_F(StructTest, Serialization_NullArrayPointers) {
    218   NamedRegionPtr region(NamedRegion::New());
    219   EXPECT_FALSE(region->name);
    220   EXPECT_FALSE(region->rects);
    221 
    222   size_t size =
    223       mojo::internal::PrepareToSerialize<NamedRegionPtr>(region, nullptr);
    224   EXPECT_EQ(8U +      // header
    225                 8U +  // name pointer
    226                 8U,   // rects pointer
    227             size);
    228 
    229   mojo::internal::FixedBufferForTesting buf(size);
    230   internal::NamedRegion_Data* data;
    231   mojo::internal::Serialize<NamedRegionPtr>(region, &buf, &data, nullptr);
    232 
    233   NamedRegionPtr region2;
    234   mojo::internal::Deserialize<NamedRegionPtr>(data, &region2, nullptr);
    235 
    236   EXPECT_FALSE(region2->name);
    237   EXPECT_FALSE(region2->rects);
    238 }
    239 
    240 // Tests deserializing structs as a newer version.
    241 TEST_F(StructTest, Versioning_OldToNew) {
    242   {
    243     MultiVersionStructV0Ptr input(MultiVersionStructV0::New());
    244     input->f_int32 = 123;
    245     MultiVersionStructPtr expected_output(MultiVersionStruct::New());
    246     expected_output->f_int32 = 123;
    247 
    248     MultiVersionStructPtr output =
    249         SerializeAndDeserialize<MultiVersionStructPtr>(std::move(input));
    250     EXPECT_TRUE(output);
    251     EXPECT_TRUE(output->Equals(*expected_output));
    252   }
    253 
    254   {
    255     MultiVersionStructV1Ptr input(MultiVersionStructV1::New());
    256     input->f_int32 = 123;
    257     input->f_rect = MakeRect(5);
    258     MultiVersionStructPtr expected_output(MultiVersionStruct::New());
    259     expected_output->f_int32 = 123;
    260     expected_output->f_rect = MakeRect(5);
    261 
    262     MultiVersionStructPtr output =
    263         SerializeAndDeserialize<MultiVersionStructPtr>(std::move(input));
    264     EXPECT_TRUE(output);
    265     EXPECT_TRUE(output->Equals(*expected_output));
    266   }
    267 
    268   {
    269     MultiVersionStructV3Ptr input(MultiVersionStructV3::New());
    270     input->f_int32 = 123;
    271     input->f_rect = MakeRect(5);
    272     input->f_string.emplace("hello");
    273     MultiVersionStructPtr expected_output(MultiVersionStruct::New());
    274     expected_output->f_int32 = 123;
    275     expected_output->f_rect = MakeRect(5);
    276     expected_output->f_string.emplace("hello");
    277 
    278     MultiVersionStructPtr output =
    279         SerializeAndDeserialize<MultiVersionStructPtr>(std::move(input));
    280     EXPECT_TRUE(output);
    281     EXPECT_TRUE(output->Equals(*expected_output));
    282   }
    283 
    284   {
    285     MultiVersionStructV5Ptr input(MultiVersionStructV5::New());
    286     input->f_int32 = 123;
    287     input->f_rect = MakeRect(5);
    288     input->f_string.emplace("hello");
    289     input->f_array.emplace(3);
    290     (*input->f_array)[0] = 10;
    291     (*input->f_array)[1] = 9;
    292     (*input->f_array)[2] = 8;
    293     MultiVersionStructPtr expected_output(MultiVersionStruct::New());
    294     expected_output->f_int32 = 123;
    295     expected_output->f_rect = MakeRect(5);
    296     expected_output->f_string.emplace("hello");
    297     expected_output->f_array.emplace(3);
    298     (*expected_output->f_array)[0] = 10;
    299     (*expected_output->f_array)[1] = 9;
    300     (*expected_output->f_array)[2] = 8;
    301 
    302     MultiVersionStructPtr output =
    303         SerializeAndDeserialize<MultiVersionStructPtr>(std::move(input));
    304     EXPECT_TRUE(output);
    305     EXPECT_TRUE(output->Equals(*expected_output));
    306   }
    307 
    308   {
    309     MultiVersionStructV7Ptr input(MultiVersionStructV7::New());
    310     input->f_int32 = 123;
    311     input->f_rect = MakeRect(5);
    312     input->f_string.emplace("hello");
    313     input->f_array.emplace(3);
    314     (*input->f_array)[0] = 10;
    315     (*input->f_array)[1] = 9;
    316     (*input->f_array)[2] = 8;
    317     MessagePipe pipe;
    318     input->f_message_pipe = std::move(pipe.handle0);
    319 
    320     MultiVersionStructPtr expected_output(MultiVersionStruct::New());
    321     expected_output->f_int32 = 123;
    322     expected_output->f_rect = MakeRect(5);
    323     expected_output->f_string.emplace("hello");
    324     expected_output->f_array.emplace(3);
    325     (*expected_output->f_array)[0] = 10;
    326     (*expected_output->f_array)[1] = 9;
    327     (*expected_output->f_array)[2] = 8;
    328     // Save the raw handle value separately so that we can compare later.
    329     MojoHandle expected_handle = input->f_message_pipe.get().value();
    330 
    331     MultiVersionStructPtr output =
    332         SerializeAndDeserialize<MultiVersionStructPtr>(std::move(input));
    333     EXPECT_TRUE(output);
    334     EXPECT_EQ(expected_handle, output->f_message_pipe.get().value());
    335     output->f_message_pipe.reset();
    336     EXPECT_TRUE(output->Equals(*expected_output));
    337   }
    338 }
    339 
    340 // Tests deserializing structs as an older version.
    341 TEST_F(StructTest, Versioning_NewToOld) {
    342   {
    343     MultiVersionStructPtr input = MakeMultiVersionStruct();
    344     MultiVersionStructV7Ptr expected_output(MultiVersionStructV7::New());
    345     expected_output->f_int32 = 123;
    346     expected_output->f_rect = MakeRect(5);
    347     expected_output->f_string.emplace("hello");
    348     expected_output->f_array.emplace(3);
    349     (*expected_output->f_array)[0] = 10;
    350     (*expected_output->f_array)[1] = 9;
    351     (*expected_output->f_array)[2] = 8;
    352     // Save the raw handle value separately so that we can compare later.
    353     MojoHandle expected_handle = input->f_message_pipe.get().value();
    354 
    355     MultiVersionStructV7Ptr output =
    356         SerializeAndDeserialize<MultiVersionStructV7Ptr>(std::move(input));
    357     EXPECT_TRUE(output);
    358     EXPECT_EQ(expected_handle, output->f_message_pipe.get().value());
    359     output->f_message_pipe.reset();
    360     EXPECT_TRUE(output->Equals(*expected_output));
    361   }
    362 
    363   {
    364     MultiVersionStructPtr input = MakeMultiVersionStruct();
    365     MultiVersionStructV5Ptr expected_output(MultiVersionStructV5::New());
    366     expected_output->f_int32 = 123;
    367     expected_output->f_rect = MakeRect(5);
    368     expected_output->f_string.emplace("hello");
    369     expected_output->f_array.emplace(3);
    370     (*expected_output->f_array)[0] = 10;
    371     (*expected_output->f_array)[1] = 9;
    372     (*expected_output->f_array)[2] = 8;
    373 
    374     MultiVersionStructV5Ptr output =
    375         SerializeAndDeserialize<MultiVersionStructV5Ptr>(std::move(input));
    376     EXPECT_TRUE(output);
    377     EXPECT_TRUE(output->Equals(*expected_output));
    378   }
    379 
    380   {
    381     MultiVersionStructPtr input = MakeMultiVersionStruct();
    382     MultiVersionStructV3Ptr expected_output(MultiVersionStructV3::New());
    383     expected_output->f_int32 = 123;
    384     expected_output->f_rect = MakeRect(5);
    385     expected_output->f_string.emplace("hello");
    386 
    387     MultiVersionStructV3Ptr output =
    388         SerializeAndDeserialize<MultiVersionStructV3Ptr>(std::move(input));
    389     EXPECT_TRUE(output);
    390     EXPECT_TRUE(output->Equals(*expected_output));
    391   }
    392 
    393   {
    394     MultiVersionStructPtr input = MakeMultiVersionStruct();
    395     MultiVersionStructV1Ptr expected_output(MultiVersionStructV1::New());
    396     expected_output->f_int32 = 123;
    397     expected_output->f_rect = MakeRect(5);
    398 
    399     MultiVersionStructV1Ptr output =
    400         SerializeAndDeserialize<MultiVersionStructV1Ptr>(std::move(input));
    401     EXPECT_TRUE(output);
    402     EXPECT_TRUE(output->Equals(*expected_output));
    403   }
    404 
    405   {
    406     MultiVersionStructPtr input = MakeMultiVersionStruct();
    407     MultiVersionStructV0Ptr expected_output(MultiVersionStructV0::New());
    408     expected_output->f_int32 = 123;
    409 
    410     MultiVersionStructV0Ptr output =
    411         SerializeAndDeserialize<MultiVersionStructV0Ptr>(std::move(input));
    412     EXPECT_TRUE(output);
    413     EXPECT_TRUE(output->Equals(*expected_output));
    414   }
    415 }
    416 
    417 // Serialization test for native struct.
    418 TEST_F(StructTest, Serialization_NativeStruct) {
    419   using Data = mojo::internal::NativeStruct_Data;
    420   {
    421     // Serialization of a null native struct.
    422     NativeStructPtr native;
    423     size_t size =
    424         mojo::internal::PrepareToSerialize<NativeStructPtr>(native, nullptr);
    425     EXPECT_EQ(0u, size);
    426     mojo::internal::FixedBufferForTesting buf(size);
    427 
    428     Data* data = nullptr;
    429     mojo::internal::Serialize<NativeStructPtr>(std::move(native), &buf, &data,
    430                                                nullptr);
    431 
    432     EXPECT_EQ(nullptr, data);
    433 
    434     NativeStructPtr output_native;
    435     mojo::internal::Deserialize<NativeStructPtr>(data, &output_native, nullptr);
    436     EXPECT_TRUE(output_native.is_null());
    437   }
    438 
    439   {
    440     // Serialization of a native struct with null data.
    441     NativeStructPtr native(NativeStruct::New());
    442     size_t size =
    443         mojo::internal::PrepareToSerialize<NativeStructPtr>(native, nullptr);
    444     EXPECT_EQ(0u, size);
    445     mojo::internal::FixedBufferForTesting buf(size);
    446 
    447     Data* data = nullptr;
    448     mojo::internal::Serialize<NativeStructPtr>(std::move(native), &buf, &data,
    449                                                nullptr);
    450 
    451     EXPECT_EQ(nullptr, data);
    452 
    453     NativeStructPtr output_native;
    454     mojo::internal::Deserialize<NativeStructPtr>(data, &output_native, nullptr);
    455     EXPECT_TRUE(output_native.is_null());
    456   }
    457 
    458   {
    459     NativeStructPtr native(NativeStruct::New());
    460     native->data = Array<uint8_t>(2);
    461     native->data[0] = 'X';
    462     native->data[1] = 'Y';
    463 
    464     size_t size =
    465         mojo::internal::PrepareToSerialize<NativeStructPtr>(native, nullptr);
    466     EXPECT_EQ(16u, size);
    467     mojo::internal::FixedBufferForTesting buf(size);
    468 
    469     Data* data = nullptr;
    470     mojo::internal::Serialize<NativeStructPtr>(std::move(native), &buf, &data,
    471                                                nullptr);
    472 
    473     EXPECT_NE(nullptr, data);
    474 
    475     NativeStructPtr output_native;
    476     mojo::internal::Deserialize<NativeStructPtr>(data, &output_native, nullptr);
    477     EXPECT_FALSE(output_native.is_null());
    478     EXPECT_FALSE(output_native->data.is_null());
    479     EXPECT_EQ(2u, output_native->data.size());
    480     EXPECT_EQ('X', output_native->data[0]);
    481     EXPECT_EQ('Y', output_native->data[1]);
    482   }
    483 }
    484 
    485 TEST_F(StructTest, Serialization_PublicAPI) {
    486   {
    487     // A null struct pointer.
    488     RectPtr null_struct;
    489     mojo::Array<uint8_t> data = Rect::Serialize(&null_struct);
    490     EXPECT_TRUE(data.empty());
    491 
    492     // Initialize it to non-null.
    493     RectPtr output(Rect::New());
    494     ASSERT_TRUE(Rect::Deserialize(std::move(data), &output));
    495     EXPECT_TRUE(output.is_null());
    496   }
    497 
    498   {
    499     // A struct with no fields.
    500     EmptyStructPtr empty_struct(EmptyStruct::New());
    501     mojo::Array<uint8_t> data = EmptyStruct::Serialize(&empty_struct);
    502     EXPECT_FALSE(data.empty());
    503 
    504     EmptyStructPtr output;
    505     ASSERT_TRUE(EmptyStruct::Deserialize(std::move(data), &output));
    506     EXPECT_FALSE(output.is_null());
    507   }
    508 
    509   {
    510     // A simple struct.
    511     RectPtr rect = MakeRect();
    512     RectPtr cloned_rect = rect.Clone();
    513     mojo::Array<uint8_t> data = Rect::Serialize(&rect);
    514 
    515     RectPtr output;
    516     ASSERT_TRUE(Rect::Deserialize(std::move(data), &output));
    517     EXPECT_TRUE(output.Equals(cloned_rect));
    518   }
    519 
    520   {
    521     // A struct containing other objects.
    522     NamedRegionPtr region(NamedRegion::New());
    523     region->name.emplace("region");
    524     region->rects.emplace(3);
    525     for (size_t i = 0; i < region->rects->size(); ++i)
    526       (*region->rects)[i] = MakeRect(static_cast<int32_t>(i) + 1);
    527 
    528     NamedRegionPtr cloned_region = region.Clone();
    529     mojo::Array<uint8_t> data = NamedRegion::Serialize(&region);
    530 
    531     // Make sure that the serialized result gets pointers encoded properly.
    532     mojo::Array<uint8_t> cloned_data = data.Clone();
    533     NamedRegionPtr output;
    534     ASSERT_TRUE(NamedRegion::Deserialize(std::move(cloned_data), &output));
    535     EXPECT_TRUE(output.Equals(cloned_region));
    536   }
    537 
    538   {
    539     // Deserialization failure.
    540     RectPtr rect = MakeRect();
    541     mojo::Array<uint8_t> data = Rect::Serialize(&rect);
    542 
    543     NamedRegionPtr output;
    544     EXPECT_FALSE(NamedRegion::Deserialize(std::move(data), &output));
    545   }
    546 }
    547 
    548 }  // namespace test
    549 }  // namespace mojo
    550