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