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. NullAndEmpty()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. Basic()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. Bool()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. Handle()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. HandlesAreClosed()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 Clone()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 Serialization_ArrayOfPOD()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 Serialization_EmptyArrayOfPOD()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 Serialization_ArrayOfArrayOfPOD()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 Serialization_ArrayOfBool()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 Serialization_ArrayOfString()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 Resize_Copyable()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 Resize_MoveOnly()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