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 |