| OLD | NEW |
| (Empty) |
| 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 "gtest/gtest.h" | |
| 6 #include "mojo/public/cpp/bindings/array.h" | |
| 7 #include "mojo/public/cpp/bindings/lib/array_internal.h" | |
| 8 #include "mojo/public/cpp/bindings/lib/array_serialization.h" | |
| 9 #include "mojo/public/cpp/bindings/lib/fixed_buffer.h" | |
| 10 #include "mojo/public/cpp/bindings/tests/container_test_util.h" | |
| 11 #include "mojo/public/cpp/bindings/tests/iterator_test_util.h" | |
| 12 #include "mojo/public/interfaces/bindings/tests/test_arrays.mojom.h" | |
| 13 #include "mojo/public/interfaces/bindings/tests/test_structs.mojom.h" | |
| 14 | |
| 15 namespace mojo { | |
| 16 namespace test { | |
| 17 namespace { | |
| 18 | |
| 19 using mojo::internal::Array_Data; | |
| 20 using mojo::internal::ArrayValidateParams; | |
| 21 using mojo::internal::FixedBufferForTesting; | |
| 22 using mojo::internal::String_Data; | |
| 23 | |
| 24 // Tests that basic Array operations work. | |
| 25 TEST(ArrayTest, Basic) { | |
| 26 auto array = Array<uint8_t>::New(8); | |
| 27 for (size_t i = 0u; i < array.size(); ++i) { | |
| 28 uint8_t val = static_cast<uint8_t>(i * 2); | |
| 29 array[i] = val; | |
| 30 EXPECT_EQ(val, array.at(i)); | |
| 31 } | |
| 32 | |
| 33 EXPECT_EQ(0u, *array.data()); | |
| 34 EXPECT_EQ(2u, *(array.data() + 1)); | |
| 35 EXPECT_EQ(4u, *(array.data() + 2)); | |
| 36 } | |
| 37 | |
| 38 TEST(ArrayTest, Testability) { | |
| 39 Array<int32_t> array; | |
| 40 EXPECT_FALSE(array); | |
| 41 EXPECT_TRUE(array.is_null()); | |
| 42 | |
| 43 array.push_back(123); | |
| 44 EXPECT_TRUE(array); | |
| 45 EXPECT_FALSE(array.is_null()); | |
| 46 } | |
| 47 | |
| 48 void NullptrConstructorTestHelper(Array<int32_t> array) { | |
| 49 EXPECT_FALSE(array); | |
| 50 EXPECT_TRUE(array.is_null()); | |
| 51 EXPECT_EQ(0u, array.size()); | |
| 52 } | |
| 53 | |
| 54 TEST(ArrayTest, NullptrConstructor) { | |
| 55 Array<int32_t> array(nullptr); | |
| 56 EXPECT_FALSE(array); | |
| 57 EXPECT_TRUE(array.is_null()); | |
| 58 EXPECT_EQ(0u, array.size()); | |
| 59 | |
| 60 array.push_back(123); | |
| 61 EXPECT_TRUE(array); | |
| 62 EXPECT_FALSE(array.is_null()); | |
| 63 EXPECT_EQ(1u, array.size()); | |
| 64 | |
| 65 // Test some implicit constructions of |Array<int32_t>| from a |nullptr|. | |
| 66 array = nullptr; | |
| 67 NullptrConstructorTestHelper(nullptr); | |
| 68 } | |
| 69 | |
| 70 // Tests that basic Array<bool> operations work. | |
| 71 TEST(ArrayTest, Bool) { | |
| 72 auto array = Array<bool>::New(64); | |
| 73 for (size_t i = 0; i < array.size(); ++i) { | |
| 74 bool val = i % 3 == 0; | |
| 75 array[i] = val; | |
| 76 EXPECT_EQ(val, array.at(i)); | |
| 77 } | |
| 78 } | |
| 79 | |
| 80 // Tests that Array<ScopedMessagePipeHandle> supports transferring handles. | |
| 81 TEST(ArrayTest, Handle) { | |
| 82 MessagePipe pipe; | |
| 83 auto handles = Array<ScopedMessagePipeHandle>::New(2); | |
| 84 handles[0] = pipe.handle0.Pass(); | |
| 85 handles[1].reset(pipe.handle1.release()); | |
| 86 | |
| 87 EXPECT_FALSE(pipe.handle0.is_valid()); | |
| 88 EXPECT_FALSE(pipe.handle1.is_valid()); | |
| 89 | |
| 90 Array<ScopedMessagePipeHandle> handles2 = handles.Pass(); | |
| 91 EXPECT_TRUE(handles2[0].is_valid()); | |
| 92 EXPECT_TRUE(handles2[1].is_valid()); | |
| 93 | |
| 94 ScopedMessagePipeHandle pipe_handle = handles2[0].Pass(); | |
| 95 EXPECT_TRUE(pipe_handle.is_valid()); | |
| 96 EXPECT_FALSE(handles2[0].is_valid()); | |
| 97 } | |
| 98 | |
| 99 // Tests that Array<ScopedMessagePipeHandle> supports closing handles. | |
| 100 TEST(ArrayTest, HandlesAreClosed) { | |
| 101 MessagePipe pipe; | |
| 102 MojoHandle pipe0_value = pipe.handle0.get().value(); | |
| 103 MojoHandle pipe1_value = pipe.handle0.get().value(); | |
| 104 | |
| 105 { | |
| 106 auto handles = Array<ScopedMessagePipeHandle>::New(2); | |
| 107 handles[0] = pipe.handle0.Pass(); | |
| 108 handles[1].reset(pipe.handle0.release()); | |
| 109 } | |
| 110 | |
| 111 // We expect the pipes to have been closed. | |
| 112 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(pipe0_value)); | |
| 113 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(pipe1_value)); | |
| 114 } | |
| 115 | |
| 116 TEST(ArrayTest, Clone) { | |
| 117 { | |
| 118 // Test POD. | |
| 119 auto array = Array<int32_t>::New(3); | |
| 120 for (size_t i = 0; i < array.size(); ++i) | |
| 121 array[i] = static_cast<int32_t>(i); | |
| 122 | |
| 123 Array<int32_t> clone_array = array.Clone(); | |
| 124 EXPECT_EQ(array.size(), clone_array.size()); | |
| 125 for (size_t i = 0; i < array.size(); ++i) | |
| 126 EXPECT_EQ(array[i], clone_array[i]); | |
| 127 } | |
| 128 | |
| 129 { | |
| 130 // Test copyable object. | |
| 131 auto array = Array<String>::New(2); | |
| 132 array[0] = "hello"; | |
| 133 array[1] = "world"; | |
| 134 | |
| 135 Array<String> clone_array = array.Clone(); | |
| 136 EXPECT_EQ(array.size(), clone_array.size()); | |
| 137 for (size_t i = 0; i < array.size(); ++i) | |
| 138 EXPECT_EQ(array[i], clone_array[i]); | |
| 139 } | |
| 140 | |
| 141 { | |
| 142 // Test struct. | |
| 143 auto array = Array<RectPtr>::New(2); | |
| 144 array[1] = Rect::New(); | |
| 145 array[1]->x = 1; | |
| 146 array[1]->y = 2; | |
| 147 array[1]->width = 3; | |
| 148 array[1]->height = 4; | |
| 149 | |
| 150 Array<RectPtr> clone_array = array.Clone(); | |
| 151 EXPECT_EQ(array.size(), clone_array.size()); | |
| 152 EXPECT_TRUE(clone_array[0].is_null()); | |
| 153 EXPECT_EQ(array[1]->x, clone_array[1]->x); | |
| 154 EXPECT_EQ(array[1]->y, clone_array[1]->y); | |
| 155 EXPECT_EQ(array[1]->width, clone_array[1]->width); | |
| 156 EXPECT_EQ(array[1]->height, clone_array[1]->height); | |
| 157 } | |
| 158 | |
| 159 { | |
| 160 // Test array of array. | |
| 161 auto array = Array<Array<int8_t>>::New(2); | |
| 162 array[1] = Array<int8_t>::New(2); | |
| 163 array[1][0] = 0; | |
| 164 array[1][1] = 1; | |
| 165 | |
| 166 Array<Array<int8_t>> clone_array = array.Clone(); | |
| 167 EXPECT_EQ(array.size(), clone_array.size()); | |
| 168 EXPECT_TRUE(clone_array[0].is_null()); | |
| 169 EXPECT_EQ(array[1].size(), clone_array[1].size()); | |
| 170 EXPECT_EQ(array[1][0], clone_array[1][0]); | |
| 171 EXPECT_EQ(array[1][1], clone_array[1][1]); | |
| 172 } | |
| 173 | |
| 174 { | |
| 175 // Test that array of handles still works although Clone() is not available. | |
| 176 auto array = Array<ScopedMessagePipeHandle>::New(10); | |
| 177 EXPECT_FALSE(array[0].is_valid()); | |
| 178 } | |
| 179 } | |
| 180 | |
| 181 TEST(ArrayTest, Serialization_ArrayOfPOD) { | |
| 182 auto array = Array<int32_t>::New(4); | |
| 183 for (size_t i = 0; i < array.size(); ++i) | |
| 184 array[i] = static_cast<int32_t>(i); | |
| 185 | |
| 186 size_t size = GetSerializedSize_(array); | |
| 187 EXPECT_EQ(8U + 4 * 4U, size); | |
| 188 | |
| 189 FixedBufferForTesting buf(size); | |
| 190 Array_Data<int32_t>* data = nullptr; | |
| 191 ArrayValidateParams validate_params(0, false, nullptr); | |
| 192 EXPECT_EQ(mojo::internal::ValidationError::NONE, | |
| 193 SerializeArray_(&array, &buf, &data, &validate_params)); | |
| 194 | |
| 195 Array<int32_t> array2; | |
| 196 Deserialize_(data, &array2); | |
| 197 | |
| 198 EXPECT_EQ(4U, array2.size()); | |
| 199 for (size_t i = 0; i < array2.size(); ++i) | |
| 200 EXPECT_EQ(static_cast<int32_t>(i), array2[i]); | |
| 201 } | |
| 202 | |
| 203 TEST(ArrayTest, Serialization_EmptyArrayOfPOD) { | |
| 204 auto array = Array<int32_t>::New(0); | |
| 205 size_t size = GetSerializedSize_(array); | |
| 206 EXPECT_EQ(8U, size); | |
| 207 | |
| 208 FixedBufferForTesting buf(size); | |
| 209 Array_Data<int32_t>* data = nullptr; | |
| 210 ArrayValidateParams validate_params(0, false, nullptr); | |
| 211 EXPECT_EQ(mojo::internal::ValidationError::NONE, | |
| 212 SerializeArray_(&array, &buf, &data, &validate_params)); | |
| 213 | |
| 214 Array<int32_t> array2; | |
| 215 Deserialize_(data, &array2); | |
| 216 EXPECT_EQ(0U, array2.size()); | |
| 217 } | |
| 218 | |
| 219 TEST(ArrayTest, Serialization_ArrayOfArrayOfPOD) { | |
| 220 auto array = Array<Array<int32_t>>::New(2); | |
| 221 for (size_t j = 0; j < array.size(); ++j) { | |
| 222 auto inner = Array<int32_t>::New(4); | |
| 223 for (size_t i = 0; i < inner.size(); ++i) | |
| 224 inner[i] = static_cast<int32_t>(i + (j * 10)); | |
| 225 array[j] = inner.Pass(); | |
| 226 } | |
| 227 | |
| 228 size_t size = GetSerializedSize_(array); | |
| 229 EXPECT_EQ(8U + 2 * 8U + 2 * (8U + 4 * 4U), size); | |
| 230 | |
| 231 FixedBufferForTesting buf(size); | |
| 232 Array_Data<Array_Data<int32_t>*>* data = nullptr; | |
| 233 ArrayValidateParams validate_params( | |
| 234 0, false, new ArrayValidateParams(0, false, nullptr)); | |
| 235 EXPECT_EQ(mojo::internal::ValidationError::NONE, | |
| 236 SerializeArray_(&array, &buf, &data, &validate_params)); | |
| 237 | |
| 238 Array<Array<int32_t>> array2; | |
| 239 Deserialize_(data, &array2); | |
| 240 | |
| 241 EXPECT_EQ(2U, array2.size()); | |
| 242 for (size_t j = 0; j < array2.size(); ++j) { | |
| 243 const Array<int32_t>& inner = array2[j]; | |
| 244 EXPECT_EQ(4U, inner.size()); | |
| 245 for (size_t i = 0; i < inner.size(); ++i) | |
| 246 EXPECT_EQ(static_cast<int32_t>(i + (j * 10)), inner[i]); | |
| 247 } | |
| 248 } | |
| 249 | |
| 250 TEST(ArrayTest, Serialization_ArrayOfScopedEnum) { | |
| 251 enum class TestEnum : int32_t { | |
| 252 E0, | |
| 253 E1, | |
| 254 E2, | |
| 255 E3, | |
| 256 }; | |
| 257 static const TestEnum TEST_VALS[] = { | |
| 258 TestEnum::E0, TestEnum::E2, TestEnum::E1, TestEnum::E3, | |
| 259 TestEnum::E2, TestEnum::E2, TestEnum::E2, TestEnum::E0, | |
| 260 }; | |
| 261 | |
| 262 auto array = Array<TestEnum>::New(MOJO_ARRAYSIZE(TEST_VALS)); | |
| 263 for (size_t i = 0; i < array.size(); ++i) | |
| 264 array[i] = TEST_VALS[i]; | |
| 265 | |
| 266 size_t size = GetSerializedSize_(array); | |
| 267 EXPECT_EQ(8U + (MOJO_ARRAYSIZE(TEST_VALS) * sizeof(int32_t)), size); | |
| 268 | |
| 269 FixedBufferForTesting buf(size); | |
| 270 Array_Data<int32_t>* data = nullptr; | |
| 271 ArrayValidateParams validate_params(0, false, nullptr); | |
| 272 SerializeArray_(&array, &buf, &data, &validate_params); | |
| 273 | |
| 274 Array<TestEnum> array2; | |
| 275 Deserialize_(data, &array2); | |
| 276 | |
| 277 EXPECT_EQ(MOJO_ARRAYSIZE(TEST_VALS), array2.size()); | |
| 278 for (size_t i = 0; i < array2.size(); ++i) | |
| 279 EXPECT_EQ(TEST_VALS[i], array2[i]); | |
| 280 } | |
| 281 | |
| 282 TEST(ArrayTest, Serialization_ArrayOfBool) { | |
| 283 auto array = Array<bool>::New(10); | |
| 284 for (size_t i = 0; i < array.size(); ++i) | |
| 285 array[i] = i % 2 ? true : false; | |
| 286 | |
| 287 size_t size = GetSerializedSize_(array); | |
| 288 EXPECT_EQ(8U + 8U, size); | |
| 289 | |
| 290 FixedBufferForTesting buf(size); | |
| 291 Array_Data<bool>* data = nullptr; | |
| 292 ArrayValidateParams validate_params(0, false, nullptr); | |
| 293 EXPECT_EQ(mojo::internal::ValidationError::NONE, | |
| 294 SerializeArray_(&array, &buf, &data, &validate_params)); | |
| 295 | |
| 296 Array<bool> array2; | |
| 297 Deserialize_(data, &array2); | |
| 298 | |
| 299 EXPECT_EQ(10U, array2.size()); | |
| 300 for (size_t i = 0; i < array2.size(); ++i) | |
| 301 EXPECT_EQ(i % 2 ? true : false, array2[i]); | |
| 302 } | |
| 303 | |
| 304 TEST(ArrayTest, Serialization_ArrayOfString) { | |
| 305 auto array = Array<String>::New(10); | |
| 306 for (size_t i = 0; i < array.size(); ++i) { | |
| 307 char c = 'A' + static_cast<char>(i); | |
| 308 array[i] = String(&c, 1); | |
| 309 } | |
| 310 | |
| 311 size_t size = GetSerializedSize_(array); | |
| 312 EXPECT_EQ(8U + // array header | |
| 313 10 * 8U + // array payload (10 pointers) | |
| 314 10 * (8U + // string header | |
| 315 8U), // string length of 1 padded to 8 | |
| 316 size); | |
| 317 | |
| 318 FixedBufferForTesting buf(size); | |
| 319 Array_Data<String_Data*>* data = nullptr; | |
| 320 ArrayValidateParams validate_params( | |
| 321 0, false, new ArrayValidateParams(0, false, nullptr)); | |
| 322 EXPECT_EQ(mojo::internal::ValidationError::NONE, | |
| 323 SerializeArray_(&array, &buf, &data, &validate_params)); | |
| 324 | |
| 325 Array<String> array2; | |
| 326 Deserialize_(data, &array2); | |
| 327 | |
| 328 EXPECT_EQ(10U, array2.size()); | |
| 329 for (size_t i = 0; i < array2.size(); ++i) { | |
| 330 char c = 'A' + static_cast<char>(i); | |
| 331 EXPECT_EQ(String(&c, 1), array2[i]); | |
| 332 } | |
| 333 } | |
| 334 | |
| 335 // Tests serializing and deserializing an Array<Handle>. | |
| 336 TEST(ArrayTest, Serialization_ArrayOfHandle) { | |
| 337 auto array = Array<ScopedHandleBase<MessagePipeHandle>>::New(4); | |
| 338 MessagePipe p0; | |
| 339 MessagePipe p1; | |
| 340 // array[0] is left invalid. | |
| 341 array[1] = p0.handle1.Pass(); | |
| 342 array[2] = p1.handle0.Pass(); | |
| 343 array[3] = p1.handle1.Pass(); | |
| 344 | |
| 345 size_t size = GetSerializedSize_(array); | |
| 346 EXPECT_EQ(8U // array header | |
| 347 + (4U * 4), // 4 handles | |
| 348 size); | |
| 349 | |
| 350 // We're going to reuse this buffer.. twice. | |
| 351 FixedBufferForTesting buf(size * 3); | |
| 352 Array_Data<MessagePipeHandle>* data = nullptr; | |
| 353 | |
| 354 // 1. Serialization should fail on non-nullable invalid Handle. | |
| 355 ArrayValidateParams validate_params(4, false, nullptr); | |
| 356 EXPECT_EQ(mojo::internal::ValidationError::UNEXPECTED_INVALID_HANDLE, | |
| 357 SerializeArray_(&array, &buf, &data, &validate_params)); | |
| 358 | |
| 359 // We failed trying to transfer the first handle, so the rest are left valid. | |
| 360 EXPECT_FALSE(array[0].is_valid()); | |
| 361 EXPECT_TRUE(array[1].is_valid()); | |
| 362 EXPECT_TRUE(array[2].is_valid()); | |
| 363 EXPECT_TRUE(array[3].is_valid()); | |
| 364 | |
| 365 // 2. Serialization should pass on nullable invalid Handle. | |
| 366 ArrayValidateParams validate_params_nullable(4, true, nullptr); | |
| 367 EXPECT_EQ(mojo::internal::ValidationError::NONE, | |
| 368 SerializeArray_(&array, &buf, &data, &validate_params_nullable)); | |
| 369 | |
| 370 EXPECT_FALSE(array[0].is_valid()); | |
| 371 EXPECT_FALSE(array[1].is_valid()); | |
| 372 EXPECT_FALSE(array[2].is_valid()); | |
| 373 EXPECT_FALSE(array[3].is_valid()); | |
| 374 | |
| 375 Deserialize_(data, &array); | |
| 376 EXPECT_FALSE(array[0].is_valid()); | |
| 377 EXPECT_TRUE(array[1].is_valid()); | |
| 378 EXPECT_TRUE(array[2].is_valid()); | |
| 379 EXPECT_TRUE(array[3].is_valid()); | |
| 380 } | |
| 381 | |
| 382 TEST(ArrayTest, Serialization_StructWithArraysOfHandles) { | |
| 383 StructWithHandles handles_struct; | |
| 384 MessagePipe handle_pair_0; | |
| 385 } | |
| 386 | |
| 387 // Test serializing and deserializing an Array<InterfacePtr>. | |
| 388 TEST(ArrayTest, Serialization_ArrayOfInterfacePtr) { | |
| 389 auto iface_array = Array<mojo::InterfaceHandle<TestInterface>>::New(1); | |
| 390 size_t size = GetSerializedSize_(iface_array); | |
| 391 EXPECT_EQ(8U // array header | |
| 392 + (8U * 1), // Interface_Data * number of elements | |
| 393 size); | |
| 394 | |
| 395 FixedBufferForTesting buf(size * 3); | |
| 396 Array_Data<mojo::internal::Interface_Data>* output = nullptr; | |
| 397 | |
| 398 // 1. Invalid InterfacePtr should fail serialization. | |
| 399 ArrayValidateParams validate_non_nullable(1, false, nullptr); | |
| 400 EXPECT_EQ( | |
| 401 mojo::internal::ValidationError::UNEXPECTED_INVALID_HANDLE, | |
| 402 SerializeArray_(&iface_array, &buf, &output, &validate_non_nullable)); | |
| 403 EXPECT_FALSE(iface_array[0].is_valid()); | |
| 404 | |
| 405 // 2. Invalid InterfacePtr should pass if array elements are nullable. | |
| 406 ArrayValidateParams validate_nullable(1, true, nullptr); | |
| 407 EXPECT_EQ(mojo::internal::ValidationError::NONE, | |
| 408 SerializeArray_(&iface_array, &buf, &output, &validate_nullable)); | |
| 409 EXPECT_FALSE(iface_array[0].is_valid()); | |
| 410 | |
| 411 // 3. Should serialize successfully if InterfacePtr is valid. | |
| 412 TestInterfacePtr iface_ptr; | |
| 413 auto iface_req = GetProxy(&iface_ptr); | |
| 414 | |
| 415 iface_array[0] = iface_ptr.Pass(); | |
| 416 EXPECT_TRUE(iface_array[0].is_valid()); | |
| 417 | |
| 418 EXPECT_EQ( | |
| 419 mojo::internal::ValidationError::NONE, | |
| 420 SerializeArray_(&iface_array, &buf, &output, &validate_non_nullable)); | |
| 421 EXPECT_FALSE(iface_array[0].is_valid()); | |
| 422 | |
| 423 Deserialize_(output, &iface_array); | |
| 424 EXPECT_TRUE(iface_array[0].is_valid()); | |
| 425 } | |
| 426 | |
| 427 // Test serializing and deserializing a struct with an Array<> of another struct | |
| 428 // which has an InterfacePtr. | |
| 429 TEST(ArrayTest, Serialization_StructWithArrayOfInterfacePtr) { | |
| 430 StructWithInterfaceArray struct_arr_iface; | |
| 431 struct_arr_iface.structs_array = Array<StructWithInterfacePtr>::New(1); | |
| 432 struct_arr_iface.nullable_structs_array = | |
| 433 Array<StructWithInterfacePtr>::New(1); | |
| 434 | |
| 435 size_t size = GetSerializedSize_(struct_arr_iface); | |
| 436 EXPECT_EQ(8U // struct header | |
| 437 + 8U // offset to |structs_array| | |
| 438 + (8U // array header | |
| 439 + 8U) // offset to StructWithInterface (nullptr) | |
| 440 + 8U // offset to |structs_nullable_array| | |
| 441 + 8U // offset to |nullable_structs_array| | |
| 442 + (8U // array header | |
| 443 + 8U) // offset to StructWithinInterface (nullptr) | |
| 444 + 8U, // offset to |nullable_structs_nullable_array| | |
| 445 size); | |
| 446 | |
| 447 FixedBufferForTesting buf(size * 2); | |
| 448 StructWithInterfaceArray::Data_* struct_arr_iface_data = nullptr; | |
| 449 // 1. This should fail because |structs_array| has an invalid InterfacePtr<> | |
| 450 // and it is not nullable. | |
| 451 EXPECT_EQ(mojo::internal::ValidationError::UNEXPECTED_NULL_POINTER, | |
| 452 Serialize_(&struct_arr_iface, &buf, &struct_arr_iface_data)); | |
| 453 | |
| 454 // 2. Adding in a struct with a valid InterfacePtr<> will let it serialize. | |
| 455 TestInterfacePtr iface_ptr; | |
| 456 auto iface_req = GetProxy(&iface_ptr); | |
| 457 | |
| 458 StructWithInterfacePtr iface_struct(StructWithInterface::New()); | |
| 459 iface_struct->iptr = iface_ptr.Pass(); | |
| 460 | |
| 461 struct_arr_iface.structs_array[0] = iface_struct.Pass(); | |
| 462 ASSERT_TRUE(struct_arr_iface.structs_array[0]->iptr.is_valid()); | |
| 463 EXPECT_EQ(mojo::internal::ValidationError::NONE, | |
| 464 Serialize_(&struct_arr_iface, &buf, &struct_arr_iface_data)); | |
| 465 | |
| 466 EXPECT_FALSE(struct_arr_iface.structs_array[0]->iptr.is_valid()); | |
| 467 | |
| 468 Deserialize_(struct_arr_iface_data, &struct_arr_iface); | |
| 469 EXPECT_TRUE(struct_arr_iface.structs_array[0]->iptr.is_valid()); | |
| 470 } | |
| 471 | |
| 472 // Test serializing and deserializing a struct with an Array<> of interface | |
| 473 // requests. | |
| 474 TEST(ArrayTest, Serialization_StructWithArrayOfIntefaceRequest) { | |
| 475 StructWithInterfaceRequests struct_arr_iface_req; | |
| 476 struct_arr_iface_req.req_array = | |
| 477 Array<InterfaceRequest<TestInterface>>::New(1); | |
| 478 struct_arr_iface_req.nullable_req_array = | |
| 479 Array<InterfaceRequest<TestInterface>>::New(1); | |
| 480 | |
| 481 size_t size = GetSerializedSize_(struct_arr_iface_req); | |
| 482 EXPECT_EQ(8U // struct header | |
| 483 + 8U // offset to |req_array| | |
| 484 + (8U // array header for |req_array| | |
| 485 + 4U // InterfaceRequest | |
| 486 + 4U) // alignment padding | |
| 487 + 8U // offset to |req_nullable_array| | |
| 488 + 8U // offset to |nullable_req_array| | |
| 489 + (8U // array header for |nullable_req_array| | |
| 490 + 4U // InterfaceRequest | |
| 491 + 4U) // alignment padding | |
| 492 + 8U, // offset to |nullable_req_nullable_array| | |
| 493 size); | |
| 494 | |
| 495 FixedBufferForTesting buf(size * 2); | |
| 496 StructWithInterfaceRequests::Data_* struct_arr_iface_req_data; | |
| 497 // 1. This should fail because |req_array| has an invalid InterfaceRequest<> | |
| 498 // and it is not nullable. | |
| 499 EXPECT_EQ( | |
| 500 mojo::internal::ValidationError::UNEXPECTED_INVALID_HANDLE, | |
| 501 Serialize_(&struct_arr_iface_req, &buf, &struct_arr_iface_req_data)); | |
| 502 | |
| 503 // 2. Adding in a valid InterfacePtr<> will let it serialize. | |
| 504 TestInterfacePtr iface_ptr; | |
| 505 struct_arr_iface_req.req_array[0] = GetProxy(&iface_ptr); | |
| 506 EXPECT_TRUE(struct_arr_iface_req.req_array[0].is_pending()); | |
| 507 | |
| 508 EXPECT_EQ( | |
| 509 mojo::internal::ValidationError::NONE, | |
| 510 Serialize_(&struct_arr_iface_req, &buf, &struct_arr_iface_req_data)); | |
| 511 | |
| 512 EXPECT_FALSE(struct_arr_iface_req.req_array[0].is_pending()); | |
| 513 | |
| 514 Deserialize_(struct_arr_iface_req_data, &struct_arr_iface_req); | |
| 515 EXPECT_TRUE(struct_arr_iface_req.req_array[0].is_pending()); | |
| 516 } | |
| 517 | |
| 518 TEST(ArrayTest, Resize_Copyable) { | |
| 519 ASSERT_EQ(0u, CopyableType::num_instances()); | |
| 520 auto array = mojo::Array<CopyableType>::New(3); | |
| 521 std::vector<CopyableType*> value_ptrs; | |
| 522 value_ptrs.push_back(array[0].ptr()); | |
| 523 value_ptrs.push_back(array[1].ptr()); | |
| 524 | |
| 525 for (size_t i = 0; i < array.size(); i++) | |
| 526 array[i].ResetCopied(); | |
| 527 | |
| 528 array.resize(2); | |
| 529 ASSERT_EQ(2u, array.size()); | |
| 530 EXPECT_EQ(array.size(), CopyableType::num_instances()); | |
| 531 for (size_t i = 0; i < array.size(); i++) { | |
| 532 EXPECT_FALSE(array[i].copied()); | |
| 533 EXPECT_EQ(value_ptrs[i], array[i].ptr()); | |
| 534 } | |
| 535 | |
| 536 array.resize(3); | |
| 537 array[2].ResetCopied(); | |
| 538 ASSERT_EQ(3u, array.size()); | |
| 539 EXPECT_EQ(array.size(), CopyableType::num_instances()); | |
| 540 for (size_t i = 0; i < array.size(); i++) | |
| 541 EXPECT_FALSE(array[i].copied()); | |
| 542 value_ptrs.push_back(array[2].ptr()); | |
| 543 | |
| 544 size_t capacity = array.storage().capacity(); | |
| 545 array.resize(capacity); | |
| 546 ASSERT_EQ(capacity, array.size()); | |
| 547 EXPECT_EQ(array.size(), CopyableType::num_instances()); | |
| 548 for (size_t i = 0; i < 3; i++) | |
| 549 EXPECT_FALSE(array[i].copied()); | |
| 550 for (size_t i = 3; i < array.size(); i++) { | |
| 551 array[i].ResetCopied(); | |
| 552 value_ptrs.push_back(array[i].ptr()); | |
| 553 } | |
| 554 | |
| 555 array.resize(capacity + 2); | |
| 556 ASSERT_EQ(capacity + 2, array.size()); | |
| 557 EXPECT_EQ(array.size(), CopyableType::num_instances()); | |
| 558 for (size_t i = 0; i < capacity; i++) { | |
| 559 EXPECT_TRUE(array[i].copied()); | |
| 560 EXPECT_EQ(value_ptrs[i], array[i].ptr()); | |
| 561 } | |
| 562 array.reset(); | |
| 563 EXPECT_EQ(0u, CopyableType::num_instances()); | |
| 564 EXPECT_FALSE(array); | |
| 565 array.resize(0); | |
| 566 EXPECT_EQ(0u, CopyableType::num_instances()); | |
| 567 EXPECT_TRUE(array); | |
| 568 } | |
| 569 | |
| 570 TEST(ArrayTest, Resize_MoveOnly) { | |
| 571 ASSERT_EQ(0u, MoveOnlyType::num_instances()); | |
| 572 auto array = mojo::Array<MoveOnlyType>::New(3); | |
| 573 std::vector<MoveOnlyType*> value_ptrs; | |
| 574 value_ptrs.push_back(array[0].ptr()); | |
| 575 value_ptrs.push_back(array[1].ptr()); | |
| 576 | |
| 577 for (size_t i = 0; i < array.size(); i++) | |
| 578 EXPECT_FALSE(array[i].moved()); | |
| 579 | |
| 580 array.resize(2); | |
| 581 ASSERT_EQ(2u, array.size()); | |
| 582 EXPECT_EQ(array.size(), MoveOnlyType::num_instances()); | |
| 583 for (size_t i = 0; i < array.size(); i++) { | |
| 584 EXPECT_FALSE(array[i].moved()); | |
| 585 EXPECT_EQ(value_ptrs[i], array[i].ptr()); | |
| 586 } | |
| 587 | |
| 588 array.resize(3); | |
| 589 ASSERT_EQ(3u, array.size()); | |
| 590 EXPECT_EQ(array.size(), MoveOnlyType::num_instances()); | |
| 591 for (size_t i = 0; i < array.size(); i++) | |
| 592 EXPECT_FALSE(array[i].moved()); | |
| 593 value_ptrs.push_back(array[2].ptr()); | |
| 594 | |
| 595 size_t capacity = array.storage().capacity(); | |
| 596 array.resize(capacity); | |
| 597 ASSERT_EQ(capacity, array.size()); | |
| 598 EXPECT_EQ(array.size(), MoveOnlyType::num_instances()); | |
| 599 for (size_t i = 0; i < array.size(); i++) | |
| 600 EXPECT_FALSE(array[i].moved()); | |
| 601 for (size_t i = 3; i < array.size(); i++) | |
| 602 value_ptrs.push_back(array[i].ptr()); | |
| 603 | |
| 604 array.resize(capacity + 2); | |
| 605 ASSERT_EQ(capacity + 2, array.size()); | |
| 606 EXPECT_EQ(array.size(), MoveOnlyType::num_instances()); | |
| 607 for (size_t i = 0; i < capacity; i++) { | |
| 608 EXPECT_TRUE(array[i].moved()); | |
| 609 EXPECT_EQ(value_ptrs[i], array[i].ptr()); | |
| 610 } | |
| 611 for (size_t i = capacity; i < array.size(); i++) | |
| 612 EXPECT_FALSE(array[i].moved()); | |
| 613 | |
| 614 array.reset(); | |
| 615 EXPECT_EQ(0u, MoveOnlyType::num_instances()); | |
| 616 EXPECT_FALSE(array); | |
| 617 array.resize(0); | |
| 618 EXPECT_EQ(0u, MoveOnlyType::num_instances()); | |
| 619 EXPECT_TRUE(array); | |
| 620 } | |
| 621 | |
| 622 TEST(ArrayTest, PushBack_Copyable) { | |
| 623 ASSERT_EQ(0u, CopyableType::num_instances()); | |
| 624 auto array = mojo::Array<CopyableType>::New(2); | |
| 625 array.reset(); | |
| 626 std::vector<CopyableType*> value_ptrs; | |
| 627 size_t capacity = array.storage().capacity(); | |
| 628 for (size_t i = 0; i < capacity; i++) { | |
| 629 CopyableType value; | |
| 630 value_ptrs.push_back(value.ptr()); | |
| 631 array.push_back(value); | |
| 632 ASSERT_EQ(i + 1, array.size()); | |
| 633 ASSERT_EQ(i + 1, value_ptrs.size()); | |
| 634 EXPECT_EQ(array.size() + 1, CopyableType::num_instances()); | |
| 635 EXPECT_TRUE(array[i].copied()); | |
| 636 EXPECT_EQ(value_ptrs[i], array[i].ptr()); | |
| 637 array[i].ResetCopied(); | |
| 638 EXPECT_TRUE(array); | |
| 639 } | |
| 640 { | |
| 641 CopyableType value; | |
| 642 value_ptrs.push_back(value.ptr()); | |
| 643 array.push_back(value); | |
| 644 EXPECT_EQ(array.size() + 1, CopyableType::num_instances()); | |
| 645 } | |
| 646 ASSERT_EQ(capacity + 1, array.size()); | |
| 647 EXPECT_EQ(array.size(), CopyableType::num_instances()); | |
| 648 | |
| 649 for (size_t i = 0; i < array.size(); i++) { | |
| 650 EXPECT_TRUE(array[i].copied()); | |
| 651 EXPECT_EQ(value_ptrs[i], array[i].ptr()); | |
| 652 } | |
| 653 array.reset(); | |
| 654 EXPECT_EQ(0u, CopyableType::num_instances()); | |
| 655 } | |
| 656 | |
| 657 TEST(ArrayTest, PushBack_MoveOnly) { | |
| 658 ASSERT_EQ(0u, MoveOnlyType::num_instances()); | |
| 659 auto array = mojo::Array<MoveOnlyType>::New(2); | |
| 660 array.reset(); | |
| 661 std::vector<MoveOnlyType*> value_ptrs; | |
| 662 size_t capacity = array.storage().capacity(); | |
| 663 for (size_t i = 0; i < capacity; i++) { | |
| 664 MoveOnlyType value; | |
| 665 value_ptrs.push_back(value.ptr()); | |
| 666 array.push_back(value.Pass()); | |
| 667 ASSERT_EQ(i + 1, array.size()); | |
| 668 ASSERT_EQ(i + 1, value_ptrs.size()); | |
| 669 EXPECT_EQ(array.size() + 1, MoveOnlyType::num_instances()); | |
| 670 EXPECT_TRUE(array[i].moved()); | |
| 671 EXPECT_EQ(value_ptrs[i], array[i].ptr()); | |
| 672 array[i].ResetMoved(); | |
| 673 EXPECT_TRUE(array); | |
| 674 } | |
| 675 { | |
| 676 MoveOnlyType value; | |
| 677 value_ptrs.push_back(value.ptr()); | |
| 678 array.push_back(value.Pass()); | |
| 679 EXPECT_EQ(array.size() + 1, MoveOnlyType::num_instances()); | |
| 680 } | |
| 681 ASSERT_EQ(capacity + 1, array.size()); | |
| 682 EXPECT_EQ(array.size(), MoveOnlyType::num_instances()); | |
| 683 | |
| 684 for (size_t i = 0; i < array.size(); i++) { | |
| 685 EXPECT_TRUE(array[i].moved()); | |
| 686 EXPECT_EQ(value_ptrs[i], array[i].ptr()); | |
| 687 } | |
| 688 array.reset(); | |
| 689 EXPECT_EQ(0u, MoveOnlyType::num_instances()); | |
| 690 } | |
| 691 | |
| 692 TEST(ArrayTest, Iterator) { | |
| 693 std::vector<int> values; | |
| 694 values.push_back(0); | |
| 695 values.push_back(1); | |
| 696 values.push_back(2); | |
| 697 values.push_back(3); | |
| 698 Array<int> arr = Array<int>::From(values); | |
| 699 | |
| 700 // Test RandomAcessIterator traits. | |
| 701 { | |
| 702 // Test +,-,+=,-=. | |
| 703 auto i1 = arr.begin(); | |
| 704 i1 += 2; | |
| 705 EXPECT_EQ(*i1, values[2]); | |
| 706 i1 -= 2; | |
| 707 EXPECT_EQ(*i1, values[0]); | |
| 708 EXPECT_EQ((i1 + 2)[1], values[3]); | |
| 709 | |
| 710 auto i2 = arr.begin() + 3; | |
| 711 EXPECT_EQ(*i2, values[3]); | |
| 712 EXPECT_EQ(*(i2 - 2), values[1]); | |
| 713 EXPECT_EQ(i2 - i1, 3); | |
| 714 | |
| 715 { | |
| 716 auto j1 = arr.begin(); | |
| 717 auto j1_cp = arr.begin(); | |
| 718 j1 += 1; | |
| 719 j1_cp++; | |
| 720 EXPECT_EQ(j1, j1_cp); | |
| 721 | |
| 722 j1 -= 1; | |
| 723 j1_cp--; | |
| 724 EXPECT_EQ(j1, j1_cp); | |
| 725 } | |
| 726 | |
| 727 // Test >, <, >=, <=. | |
| 728 EXPECT_GT(i2, i1); | |
| 729 EXPECT_LT(i1, i2); | |
| 730 EXPECT_GE(i2, i1); | |
| 731 EXPECT_LE(i1, i2); | |
| 732 } | |
| 733 | |
| 734 { | |
| 735 SCOPED_TRACE("Array iterator bidirectionality test."); | |
| 736 ExpectBidiIteratorConcept(arr.begin(), arr.end(), values); | |
| 737 ExpectBidiMutableIteratorConcept(arr.begin(), arr.end(), values); | |
| 738 } | |
| 739 } | |
| 740 | |
| 741 // Test serializing and deserializing of an array with null elements. | |
| 742 TEST(ArrayTest, Serialization_ArrayOfStructPtr) { | |
| 743 ArrayValidateParams validate_nullable(2, true, nullptr); | |
| 744 ArrayValidateParams validate_non_nullable(2, false, nullptr); | |
| 745 | |
| 746 Array<RectPtr> array = Array<RectPtr>::New(2); | |
| 747 array[1] = Rect::New(); | |
| 748 array[1]->x = 1; | |
| 749 array[1]->y = 2; | |
| 750 array[1]->width = 3; | |
| 751 array[1]->height = 4; | |
| 752 | |
| 753 size_t size_with_null = GetSerializedSize_(array); | |
| 754 EXPECT_EQ(8U + // array header | |
| 755 2 * 8U + // array payload (2 pointers) | |
| 756 8U + 4 * 4U, // struct header + contents (4 int32) | |
| 757 size_with_null); | |
| 758 Array_Data<Rect::Data_*>* output_with_null = nullptr; | |
| 759 | |
| 760 // 1. Array with non-nullable structs should fail serialization due to | |
| 761 // the null first element. | |
| 762 { | |
| 763 FixedBufferForTesting buf_with_null(size_with_null); | |
| 764 EXPECT_EQ(mojo::internal::ValidationError::UNEXPECTED_NULL_POINTER, | |
| 765 SerializeArray_(&array, &buf_with_null, &output_with_null, | |
| 766 &validate_non_nullable)); | |
| 767 } | |
| 768 | |
| 769 // 2. Array with nullable structs should succeed. | |
| 770 { | |
| 771 FixedBufferForTesting buf_with_null(size_with_null); | |
| 772 EXPECT_EQ(mojo::internal::ValidationError::NONE, | |
| 773 SerializeArray_(&array, &buf_with_null, &output_with_null, | |
| 774 &validate_nullable)); | |
| 775 | |
| 776 Array<RectPtr> array2; | |
| 777 Deserialize_(output_with_null, &array2); | |
| 778 EXPECT_TRUE(array2[0].is_null()); | |
| 779 EXPECT_FALSE(array2[1].is_null()); | |
| 780 EXPECT_EQ(1, array2[1]->x); | |
| 781 EXPECT_EQ(2, array2[1]->y); | |
| 782 EXPECT_EQ(3, array2[1]->width); | |
| 783 EXPECT_EQ(4, array2[1]->height); | |
| 784 } | |
| 785 | |
| 786 // 3. Array with non-nullable structs should succeed after we fill in | |
| 787 // the missing first element. | |
| 788 { | |
| 789 array[0] = Rect::New(); | |
| 790 array[0]->x = -1; | |
| 791 array[0]->y = -2; | |
| 792 array[0]->width = -3; | |
| 793 array[0]->height = -4; | |
| 794 | |
| 795 size_t size_without_null = GetSerializedSize_(array); | |
| 796 EXPECT_EQ(8U + // array header | |
| 797 2 * 8U + // array payload (2 pointers) | |
| 798 2 * (8U + 4 * 4U), // struct header + contents (4 int32) | |
| 799 size_without_null); | |
| 800 | |
| 801 FixedBufferForTesting buf_without_null(size_without_null); | |
| 802 Array_Data<Rect::Data_*>* output_without_null = nullptr; | |
| 803 EXPECT_EQ(mojo::internal::ValidationError::NONE, | |
| 804 SerializeArray_(&array, &buf_without_null, &output_without_null, | |
| 805 &validate_non_nullable)); | |
| 806 | |
| 807 Array<RectPtr> array3; | |
| 808 Deserialize_(output_without_null, &array3); | |
| 809 EXPECT_FALSE(array3[0].is_null()); | |
| 810 EXPECT_EQ(-1, array3[0]->x); | |
| 811 EXPECT_EQ(-2, array3[0]->y); | |
| 812 EXPECT_EQ(-3, array3[0]->width); | |
| 813 EXPECT_EQ(-4, array3[0]->height); | |
| 814 EXPECT_FALSE(array3[1].is_null()); | |
| 815 EXPECT_EQ(1, array3[1]->x); | |
| 816 EXPECT_EQ(2, array3[1]->y); | |
| 817 EXPECT_EQ(3, array3[1]->width); | |
| 818 EXPECT_EQ(4, array3[1]->height); | |
| 819 } | |
| 820 } | |
| 821 | |
| 822 } // namespace | |
| 823 } // namespace test | |
| 824 } // namespace mojo | |
| OLD | NEW |