Home | History | Annotate | Download | only in tests
      1 // Copyright 2016 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 
      9 #include "mojo/public/cpp/bindings/lib/array_internal.h"
     10 #include "mojo/public/cpp/bindings/lib/fixed_buffer.h"
     11 #include "mojo/public/cpp/bindings/lib/serialization.h"
     12 #include "mojo/public/cpp/bindings/tests/container_test_util.h"
     13 #include "mojo/public/interfaces/bindings/tests/test_structs.mojom.h"
     14 #include "testing/gtest/include/gtest/gtest.h"
     15 
     16 namespace mojo {
     17 namespace test {
     18 
     19 // Common tests for both mojo::Array and mojo::WTFArray.
     20 template <template <typename...> class ArrayType>
     21 class ArrayCommonTest {
     22  public:
     23   // Tests null and empty arrays.
     24   static void NullAndEmpty() {
     25     ArrayType<char> array0;
     26     EXPECT_TRUE(array0.empty());
     27     EXPECT_FALSE(array0.is_null());
     28     array0 = nullptr;
     29     EXPECT_TRUE(array0.is_null());
     30     EXPECT_FALSE(array0.empty());
     31 
     32     ArrayType<char> array1(nullptr);
     33     EXPECT_TRUE(array1.is_null());
     34     EXPECT_FALSE(array1.empty());
     35     array1.SetToEmpty();
     36     EXPECT_TRUE(array1.empty());
     37     EXPECT_FALSE(array1.is_null());
     38   }
     39 
     40   // Tests that basic array operations work.
     41   static void Basic() {
     42     ArrayType<char> array(8);
     43     for (size_t i = 0; i < array.size(); ++i) {
     44       char val = static_cast<char>(i * 2);
     45       array[i] = val;
     46       EXPECT_EQ(val, array.at(i));
     47     }
     48   }
     49 
     50   // Tests that basic ArrayType<bool> operations work.
     51   static void Bool() {
     52     ArrayType<bool> array(64);
     53     for (size_t i = 0; i < array.size(); ++i) {
     54       bool val = i % 3 == 0;
     55       array[i] = val;
     56       EXPECT_EQ(val, array.at(i));
     57     }
     58   }
     59 
     60   // Tests that ArrayType<ScopedMessagePipeHandle> supports transferring
     61   // handles.
     62   static void Handle() {
     63     MessagePipe pipe;
     64     ArrayType<ScopedMessagePipeHandle> handles(2);
     65     handles[0] = std::move(pipe.handle0);
     66     handles[1].reset(pipe.handle1.release());
     67 
     68     EXPECT_FALSE(pipe.handle0.is_valid());
     69     EXPECT_FALSE(pipe.handle1.is_valid());
     70 
     71     ArrayType<ScopedMessagePipeHandle> handles2 = std::move(handles);
     72     EXPECT_TRUE(handles2[0].is_valid());
     73     EXPECT_TRUE(handles2[1].is_valid());
     74 
     75     ScopedMessagePipeHandle pipe_handle = std::move(handles2[0]);
     76     EXPECT_TRUE(pipe_handle.is_valid());
     77     EXPECT_FALSE(handles2[0].is_valid());
     78   }
     79 
     80   // Tests that ArrayType<ScopedMessagePipeHandle> supports closing handles.
     81   static void HandlesAreClosed() {
     82     MessagePipe pipe;
     83     MojoHandle pipe0_value = pipe.handle0.get().value();
     84     MojoHandle pipe1_value = pipe.handle0.get().value();
     85 
     86     {
     87       ArrayType<ScopedMessagePipeHandle> handles(2);
     88       handles[0] = std::move(pipe.handle0);
     89       handles[1].reset(pipe.handle0.release());
     90     }
     91 
     92     // We expect the pipes to have been closed.
     93     EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(pipe0_value));
     94     EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(pipe1_value));
     95   }
     96 
     97   static void Clone() {
     98     {
     99       // Test POD.
    100       ArrayType<int32_t> array(3);
    101       for (size_t i = 0; i < array.size(); ++i)
    102         array[i] = static_cast<int32_t>(i);
    103 
    104       ArrayType<int32_t> clone_array = array.Clone();
    105       EXPECT_EQ(array.size(), clone_array.size());
    106       for (size_t i = 0; i < array.size(); ++i)
    107         EXPECT_EQ(array[i], clone_array[i]);
    108     }
    109 
    110     {
    111       // Test copyable object.
    112       ArrayType<String> array(2);
    113       array[0] = "hello";
    114       array[1] = "world";
    115 
    116       ArrayType<String> clone_array = array.Clone();
    117       EXPECT_EQ(array.size(), clone_array.size());
    118       for (size_t i = 0; i < array.size(); ++i)
    119         EXPECT_EQ(array[i], clone_array[i]);
    120     }
    121 
    122     {
    123       // Test struct.
    124       ArrayType<RectPtr> array(2);
    125       array[1] = Rect::New();
    126       array[1]->x = 1;
    127       array[1]->y = 2;
    128       array[1]->width = 3;
    129       array[1]->height = 4;
    130 
    131       ArrayType<RectPtr> clone_array = array.Clone();
    132       EXPECT_EQ(array.size(), clone_array.size());
    133       EXPECT_TRUE(clone_array[0].is_null());
    134       EXPECT_EQ(array[1]->x, clone_array[1]->x);
    135       EXPECT_EQ(array[1]->y, clone_array[1]->y);
    136       EXPECT_EQ(array[1]->width, clone_array[1]->width);
    137       EXPECT_EQ(array[1]->height, clone_array[1]->height);
    138     }
    139 
    140     {
    141       // Test array of array.
    142       ArrayType<ArrayType<int8_t>> array(2);
    143       array[0] = nullptr;
    144       array[1] = ArrayType<int8_t>(2);
    145       array[1][0] = 0;
    146       array[1][1] = 1;
    147 
    148       ArrayType<ArrayType<int8_t>> clone_array = array.Clone();
    149       EXPECT_EQ(array.size(), clone_array.size());
    150       EXPECT_TRUE(clone_array[0].is_null());
    151       EXPECT_EQ(array[1].size(), clone_array[1].size());
    152       EXPECT_EQ(array[1][0], clone_array[1][0]);
    153       EXPECT_EQ(array[1][1], clone_array[1][1]);
    154     }
    155 
    156     {
    157       // Test that array of handles still works although Clone() is not
    158       // available.
    159       ArrayType<ScopedMessagePipeHandle> array(10);
    160       EXPECT_FALSE(array[0].is_valid());
    161     }
    162   }
    163 
    164   static void Serialization_ArrayOfPOD() {
    165     ArrayType<int32_t> array(4);
    166     for (size_t i = 0; i < array.size(); ++i)
    167       array[i] = static_cast<int32_t>(i);
    168 
    169     size_t size =
    170         mojo::internal::PrepareToSerialize<Array<int32_t>>(array, nullptr);
    171     EXPECT_EQ(8U + 4 * 4U, size);
    172 
    173     mojo::internal::FixedBufferForTesting buf(size);
    174     mojo::internal::Array_Data<int32_t>* data;
    175     mojo::internal::ContainerValidateParams validate_params(0, false, nullptr);
    176     mojo::internal::Serialize<Array<int32_t>>(array, &buf, &data,
    177                                               &validate_params, nullptr);
    178 
    179     ArrayType<int32_t> array2;
    180     mojo::internal::Deserialize<Array<int32_t>>(data, &array2, nullptr);
    181 
    182     EXPECT_EQ(4U, array2.size());
    183     for (size_t i = 0; i < array2.size(); ++i)
    184       EXPECT_EQ(static_cast<int32_t>(i), array2[i]);
    185   }
    186 
    187   static void Serialization_EmptyArrayOfPOD() {
    188     ArrayType<int32_t> array;
    189     size_t size =
    190         mojo::internal::PrepareToSerialize<Array<int32_t>>(array, nullptr);
    191     EXPECT_EQ(8U, size);
    192 
    193     mojo::internal::FixedBufferForTesting buf(size);
    194     mojo::internal::Array_Data<int32_t>* data;
    195     mojo::internal::ContainerValidateParams validate_params(0, false, nullptr);
    196     mojo::internal::Serialize<Array<int32_t>>(array, &buf, &data,
    197                                               &validate_params, nullptr);
    198 
    199     ArrayType<int32_t> array2;
    200     mojo::internal::Deserialize<Array<int32_t>>(data, &array2, nullptr);
    201     EXPECT_EQ(0U, array2.size());
    202   }
    203 
    204   static void Serialization_ArrayOfArrayOfPOD() {
    205     ArrayType<ArrayType<int32_t>> array(2);
    206     for (size_t j = 0; j < array.size(); ++j) {
    207       ArrayType<int32_t> inner(4);
    208       for (size_t i = 0; i < inner.size(); ++i)
    209         inner[i] = static_cast<int32_t>(i + (j * 10));
    210       array[j] = std::move(inner);
    211     }
    212 
    213     size_t size = mojo::internal::PrepareToSerialize<Array<Array<int32_t>>>(
    214         array, nullptr);
    215     EXPECT_EQ(8U + 2 * 8U + 2 * (8U + 4 * 4U), size);
    216 
    217     mojo::internal::FixedBufferForTesting buf(size);
    218     typename mojo::internal::MojomTypeTraits<Array<Array<int32_t>>>::Data* data;
    219     mojo::internal::ContainerValidateParams validate_params(
    220         0, false,
    221         new mojo::internal::ContainerValidateParams(0, false, nullptr));
    222     mojo::internal::Serialize<Array<Array<int32_t>>>(array, &buf, &data,
    223                                                      &validate_params, nullptr);
    224 
    225     ArrayType<ArrayType<int32_t>> array2;
    226     mojo::internal::Deserialize<Array<Array<int32_t>>>(data, &array2, nullptr);
    227 
    228     EXPECT_EQ(2U, array2.size());
    229     for (size_t j = 0; j < array2.size(); ++j) {
    230       const ArrayType<int32_t>& inner = array2[j];
    231       EXPECT_EQ(4U, inner.size());
    232       for (size_t i = 0; i < inner.size(); ++i)
    233         EXPECT_EQ(static_cast<int32_t>(i + (j * 10)), inner[i]);
    234     }
    235   }
    236 
    237   static void Serialization_ArrayOfBool() {
    238     ArrayType<bool> array(10);
    239     for (size_t i = 0; i < array.size(); ++i)
    240       array[i] = i % 2 ? true : false;
    241 
    242     size_t size =
    243         mojo::internal::PrepareToSerialize<Array<bool>>(array, nullptr);
    244     EXPECT_EQ(8U + 8U, size);
    245 
    246     mojo::internal::FixedBufferForTesting buf(size);
    247     mojo::internal::Array_Data<bool>* data;
    248     mojo::internal::ContainerValidateParams validate_params(0, false, nullptr);
    249     mojo::internal::Serialize<Array<bool>>(array, &buf, &data, &validate_params,
    250                                            nullptr);
    251 
    252     ArrayType<bool> array2;
    253     mojo::internal::Deserialize<Array<bool>>(data, &array2, nullptr);
    254 
    255     EXPECT_EQ(10U, array2.size());
    256     for (size_t i = 0; i < array2.size(); ++i)
    257       EXPECT_EQ(i % 2 ? true : false, array2[i]);
    258   }
    259 
    260   static void Serialization_ArrayOfString() {
    261     ArrayType<String> array(10);
    262     for (size_t i = 0; i < array.size(); ++i) {
    263       char c = 'A' + static_cast<char>(i);
    264       array[i] = String(&c, 1);
    265     }
    266 
    267     size_t size =
    268         mojo::internal::PrepareToSerialize<Array<String>>(array, nullptr);
    269     EXPECT_EQ(8U +            // array header
    270                   10 * 8U +   // array payload (10 pointers)
    271                   10 * (8U +  // string header
    272                         8U),  // string length of 1 padded to 8
    273               size);
    274 
    275     mojo::internal::FixedBufferForTesting buf(size);
    276     typename mojo::internal::MojomTypeTraits<Array<String>>::Data* data;
    277     mojo::internal::ContainerValidateParams validate_params(
    278         0, false,
    279         new mojo::internal::ContainerValidateParams(0, false, nullptr));
    280     mojo::internal::Serialize<Array<String>>(array, &buf, &data,
    281                                              &validate_params, nullptr);
    282 
    283     ArrayType<String> array2;
    284     mojo::internal::Deserialize<Array<String>>(data, &array2, nullptr);
    285 
    286     EXPECT_EQ(10U, array2.size());
    287     for (size_t i = 0; i < array2.size(); ++i) {
    288       char c = 'A' + static_cast<char>(i);
    289       EXPECT_EQ(String(&c, 1), array2[i]);
    290     }
    291   }
    292 
    293   static void Resize_Copyable() {
    294     ASSERT_EQ(0u, CopyableType::num_instances());
    295     ArrayType<CopyableType> array(3);
    296     std::vector<CopyableType*> value_ptrs;
    297     value_ptrs.push_back(array[0].ptr());
    298     value_ptrs.push_back(array[1].ptr());
    299 
    300     for (size_t i = 0; i < array.size(); i++)
    301       array[i].ResetCopied();
    302 
    303     array.resize(2);
    304     ASSERT_EQ(2u, array.size());
    305     EXPECT_EQ(array.size(), CopyableType::num_instances());
    306     for (size_t i = 0; i < array.size(); i++) {
    307       EXPECT_FALSE(array[i].copied());
    308       EXPECT_EQ(value_ptrs[i], array[i].ptr());
    309     }
    310 
    311     array.resize(3);
    312     array[2].ResetCopied();
    313     ASSERT_EQ(3u, array.size());
    314     EXPECT_EQ(array.size(), CopyableType::num_instances());
    315     for (size_t i = 0; i < array.size(); i++)
    316       EXPECT_FALSE(array[i].copied());
    317     value_ptrs.push_back(array[2].ptr());
    318 
    319     size_t capacity = array.storage().capacity();
    320     array.resize(capacity);
    321     ASSERT_EQ(capacity, array.size());
    322     EXPECT_EQ(array.size(), CopyableType::num_instances());
    323     for (size_t i = 0; i < 3; i++)
    324       EXPECT_FALSE(array[i].copied());
    325     for (size_t i = 3; i < array.size(); i++) {
    326       array[i].ResetCopied();
    327       value_ptrs.push_back(array[i].ptr());
    328     }
    329 
    330     array.resize(capacity + 2);
    331     ASSERT_EQ(capacity + 2, array.size());
    332     EXPECT_EQ(array.size(), CopyableType::num_instances());
    333     for (size_t i = 0; i < capacity; i++) {
    334       EXPECT_TRUE(array[i].copied());
    335       EXPECT_EQ(value_ptrs[i], array[i].ptr());
    336     }
    337     array = nullptr;
    338     EXPECT_EQ(0u, CopyableType::num_instances());
    339     EXPECT_FALSE(array);
    340     array.resize(0);
    341     EXPECT_EQ(0u, CopyableType::num_instances());
    342     EXPECT_TRUE(array);
    343   }
    344 
    345   static void Resize_MoveOnly() {
    346     ASSERT_EQ(0u, MoveOnlyType::num_instances());
    347     ArrayType<MoveOnlyType> array(3);
    348     std::vector<MoveOnlyType*> value_ptrs;
    349     value_ptrs.push_back(array[0].ptr());
    350     value_ptrs.push_back(array[1].ptr());
    351 
    352     for (size_t i = 0; i < array.size(); i++)
    353       EXPECT_FALSE(array[i].moved());
    354 
    355     array.resize(2);
    356     ASSERT_EQ(2u, array.size());
    357     EXPECT_EQ(array.size(), MoveOnlyType::num_instances());
    358     for (size_t i = 0; i < array.size(); i++) {
    359       EXPECT_FALSE(array[i].moved());
    360       EXPECT_EQ(value_ptrs[i], array[i].ptr());
    361     }
    362 
    363     array.resize(3);
    364     ASSERT_EQ(3u, array.size());
    365     EXPECT_EQ(array.size(), MoveOnlyType::num_instances());
    366     for (size_t i = 0; i < array.size(); i++)
    367       EXPECT_FALSE(array[i].moved());
    368     value_ptrs.push_back(array[2].ptr());
    369 
    370     size_t capacity = array.storage().capacity();
    371     array.resize(capacity);
    372     ASSERT_EQ(capacity, array.size());
    373     EXPECT_EQ(array.size(), MoveOnlyType::num_instances());
    374     for (size_t i = 0; i < array.size(); i++)
    375       EXPECT_FALSE(array[i].moved());
    376     for (size_t i = 3; i < array.size(); i++)
    377       value_ptrs.push_back(array[i].ptr());
    378 
    379     array.resize(capacity + 2);
    380     ASSERT_EQ(capacity + 2, array.size());
    381     EXPECT_EQ(array.size(), MoveOnlyType::num_instances());
    382     for (size_t i = 0; i < capacity; i++) {
    383       EXPECT_TRUE(array[i].moved());
    384       EXPECT_EQ(value_ptrs[i], array[i].ptr());
    385     }
    386     for (size_t i = capacity; i < array.size(); i++)
    387       EXPECT_FALSE(array[i].moved());
    388 
    389     array = nullptr;
    390     EXPECT_EQ(0u, MoveOnlyType::num_instances());
    391     EXPECT_FALSE(array);
    392     array.resize(0);
    393     EXPECT_EQ(0u, MoveOnlyType::num_instances());
    394     EXPECT_TRUE(array);
    395   }
    396 };
    397 
    398 #define ARRAY_COMMON_TEST(ArrayType, test_name) \
    399   TEST_F(ArrayType##Test, test_name) {          \
    400     ArrayCommonTest<ArrayType>::test_name();    \
    401   }
    402 
    403 }  // namespace test
    404 }  // namespace mojo
    405