| OLD | NEW |
| (Empty) |
| 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<std::string> array(2); | |
| 113 array[0] = "hello"; | |
| 114 array[1] = "world"; | |
| 115 | |
| 116 ArrayType<std::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 = mojo::internal::PrepareToSerialize<ArrayDataView<int32_t>>( | |
| 170 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<ArrayDataView<int32_t>>( | |
| 177 array, &buf, &data, &validate_params, nullptr); | |
| 178 | |
| 179 ArrayType<int32_t> array2; | |
| 180 mojo::internal::Deserialize<ArrayDataView<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 = mojo::internal::PrepareToSerialize<ArrayDataView<int32_t>>( | |
| 190 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<ArrayDataView<int32_t>>( | |
| 197 array, &buf, &data, &validate_params, nullptr); | |
| 198 | |
| 199 ArrayType<int32_t> array2; | |
| 200 mojo::internal::Deserialize<ArrayDataView<int32_t>>(data, &array2, nullptr); | |
| 201 EXPECT_EQ(0U, array2.size()); | |
| 202 } | |
| 203 | |
| 204 static void Serialization_ArrayOfArrayOfPOD() { | |
| 205 using MojomType = ArrayDataView<ArrayDataView<int32_t>>; | |
| 206 ArrayType<ArrayType<int32_t>> array(2); | |
| 207 for (size_t j = 0; j < array.size(); ++j) { | |
| 208 ArrayType<int32_t> inner(4); | |
| 209 for (size_t i = 0; i < inner.size(); ++i) | |
| 210 inner[i] = static_cast<int32_t>(i + (j * 10)); | |
| 211 array[j] = std::move(inner); | |
| 212 } | |
| 213 | |
| 214 size_t size = mojo::internal::PrepareToSerialize<MojomType>(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<MojomType>::Data* data; | |
| 219 mojo::internal::ContainerValidateParams validate_params( | |
| 220 0, false, | |
| 221 new mojo::internal::ContainerValidateParams(0, false, nullptr)); | |
| 222 mojo::internal::Serialize<MojomType>(array, &buf, &data, &validate_params, | |
| 223 nullptr); | |
| 224 | |
| 225 ArrayType<ArrayType<int32_t>> array2; | |
| 226 mojo::internal::Deserialize<MojomType>(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<ArrayDataView<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<ArrayDataView<bool>>(array, &buf, &data, | |
| 250 &validate_params, nullptr); | |
| 251 | |
| 252 ArrayType<bool> array2; | |
| 253 mojo::internal::Deserialize<ArrayDataView<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 using MojomType = ArrayDataView<StringDataView>; | |
| 262 ArrayType<std::string> array(10); | |
| 263 for (size_t i = 0; i < array.size(); ++i) { | |
| 264 char c = 'A' + static_cast<char>(i); | |
| 265 array[i] = std::string(&c, 1); | |
| 266 } | |
| 267 | |
| 268 size_t size = mojo::internal::PrepareToSerialize<MojomType>(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<MojomType>::Data* data; | |
| 277 mojo::internal::ContainerValidateParams validate_params( | |
| 278 0, false, | |
| 279 new mojo::internal::ContainerValidateParams(0, false, nullptr)); | |
| 280 mojo::internal::Serialize<MojomType>(array, &buf, &data, &validate_params, | |
| 281 nullptr); | |
| 282 | |
| 283 ArrayType<std::string> array2; | |
| 284 mojo::internal::Deserialize<MojomType>(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(std::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 | |
| OLD | NEW |