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 |