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