• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <stddef.h>
6 #include <stdint.h>
7 #include <utility>
8 
9 #include "mojo/public/cpp/bindings/lib/array_internal.h"
10 #include "mojo/public/cpp/bindings/lib/fixed_buffer.h"
11 #include "mojo/public/cpp/bindings/lib/serialization.h"
12 #include "mojo/public/cpp/bindings/tests/container_test_util.h"
13 #include "mojo/public/interfaces/bindings/tests/test_structs.mojom.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 
16 namespace mojo {
17 namespace test {
18 
19 // Common tests for both mojo::Array and mojo::WTFArray.
20 template <template <typename...> class ArrayType>
21 class ArrayCommonTest {
22  public:
23   // Tests null and empty arrays.
NullAndEmpty()24   static void NullAndEmpty() {
25     ArrayType<char> array0;
26     EXPECT_TRUE(array0.empty());
27     EXPECT_FALSE(array0.is_null());
28     array0 = nullptr;
29     EXPECT_TRUE(array0.is_null());
30     EXPECT_FALSE(array0.empty());
31 
32     ArrayType<char> array1(nullptr);
33     EXPECT_TRUE(array1.is_null());
34     EXPECT_FALSE(array1.empty());
35     array1.SetToEmpty();
36     EXPECT_TRUE(array1.empty());
37     EXPECT_FALSE(array1.is_null());
38   }
39 
40   // Tests that basic array operations work.
Basic()41   static void Basic() {
42     ArrayType<char> array(8);
43     for (size_t i = 0; i < array.size(); ++i) {
44       char val = static_cast<char>(i * 2);
45       array[i] = val;
46       EXPECT_EQ(val, array.at(i));
47     }
48   }
49 
50   // Tests that basic ArrayType<bool> operations work.
Bool()51   static void Bool() {
52     ArrayType<bool> array(64);
53     for (size_t i = 0; i < array.size(); ++i) {
54       bool val = i % 3 == 0;
55       array[i] = val;
56       EXPECT_EQ(val, array.at(i));
57     }
58   }
59 
60   // Tests that ArrayType<ScopedMessagePipeHandle> supports transferring
61   // handles.
Handle()62   static void Handle() {
63     MessagePipe pipe;
64     ArrayType<ScopedMessagePipeHandle> handles(2);
65     handles[0] = std::move(pipe.handle0);
66     handles[1].reset(pipe.handle1.release());
67 
68     EXPECT_FALSE(pipe.handle0.is_valid());
69     EXPECT_FALSE(pipe.handle1.is_valid());
70 
71     ArrayType<ScopedMessagePipeHandle> handles2 = std::move(handles);
72     EXPECT_TRUE(handles2[0].is_valid());
73     EXPECT_TRUE(handles2[1].is_valid());
74 
75     ScopedMessagePipeHandle pipe_handle = std::move(handles2[0]);
76     EXPECT_TRUE(pipe_handle.is_valid());
77     EXPECT_FALSE(handles2[0].is_valid());
78   }
79 
80   // Tests that ArrayType<ScopedMessagePipeHandle> supports closing handles.
HandlesAreClosed()81   static void HandlesAreClosed() {
82     MessagePipe pipe;
83     MojoHandle pipe0_value = pipe.handle0.get().value();
84     MojoHandle pipe1_value = pipe.handle0.get().value();
85 
86     {
87       ArrayType<ScopedMessagePipeHandle> handles(2);
88       handles[0] = std::move(pipe.handle0);
89       handles[1].reset(pipe.handle0.release());
90     }
91 
92     // We expect the pipes to have been closed.
93     EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(pipe0_value));
94     EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(pipe1_value));
95   }
96 
Clone()97   static void Clone() {
98     {
99       // Test POD.
100       ArrayType<int32_t> array(3);
101       for (size_t i = 0; i < array.size(); ++i)
102         array[i] = static_cast<int32_t>(i);
103 
104       ArrayType<int32_t> clone_array = array.Clone();
105       EXPECT_EQ(array.size(), clone_array.size());
106       for (size_t i = 0; i < array.size(); ++i)
107         EXPECT_EQ(array[i], clone_array[i]);
108     }
109 
110     {
111       // Test copyable object.
112       ArrayType<String> array(2);
113       array[0] = "hello";
114       array[1] = "world";
115 
116       ArrayType<String> clone_array = array.Clone();
117       EXPECT_EQ(array.size(), clone_array.size());
118       for (size_t i = 0; i < array.size(); ++i)
119         EXPECT_EQ(array[i], clone_array[i]);
120     }
121 
122     {
123       // Test struct.
124       ArrayType<RectPtr> array(2);
125       array[1] = Rect::New();
126       array[1]->x = 1;
127       array[1]->y = 2;
128       array[1]->width = 3;
129       array[1]->height = 4;
130 
131       ArrayType<RectPtr> clone_array = array.Clone();
132       EXPECT_EQ(array.size(), clone_array.size());
133       EXPECT_TRUE(clone_array[0].is_null());
134       EXPECT_EQ(array[1]->x, clone_array[1]->x);
135       EXPECT_EQ(array[1]->y, clone_array[1]->y);
136       EXPECT_EQ(array[1]->width, clone_array[1]->width);
137       EXPECT_EQ(array[1]->height, clone_array[1]->height);
138     }
139 
140     {
141       // Test array of array.
142       ArrayType<ArrayType<int8_t>> array(2);
143       array[0] = nullptr;
144       array[1] = ArrayType<int8_t>(2);
145       array[1][0] = 0;
146       array[1][1] = 1;
147 
148       ArrayType<ArrayType<int8_t>> clone_array = array.Clone();
149       EXPECT_EQ(array.size(), clone_array.size());
150       EXPECT_TRUE(clone_array[0].is_null());
151       EXPECT_EQ(array[1].size(), clone_array[1].size());
152       EXPECT_EQ(array[1][0], clone_array[1][0]);
153       EXPECT_EQ(array[1][1], clone_array[1][1]);
154     }
155 
156     {
157       // Test that array of handles still works although Clone() is not
158       // available.
159       ArrayType<ScopedMessagePipeHandle> array(10);
160       EXPECT_FALSE(array[0].is_valid());
161     }
162   }
163 
Serialization_ArrayOfPOD()164   static void Serialization_ArrayOfPOD() {
165     ArrayType<int32_t> array(4);
166     for (size_t i = 0; i < array.size(); ++i)
167       array[i] = static_cast<int32_t>(i);
168 
169     size_t size =
170         mojo::internal::PrepareToSerialize<Array<int32_t>>(array, nullptr);
171     EXPECT_EQ(8U + 4 * 4U, size);
172 
173     mojo::internal::FixedBufferForTesting buf(size);
174     mojo::internal::Array_Data<int32_t>* data;
175     mojo::internal::ContainerValidateParams validate_params(0, false, nullptr);
176     mojo::internal::Serialize<Array<int32_t>>(array, &buf, &data,
177                                               &validate_params, nullptr);
178 
179     ArrayType<int32_t> array2;
180     mojo::internal::Deserialize<Array<int32_t>>(data, &array2, nullptr);
181 
182     EXPECT_EQ(4U, array2.size());
183     for (size_t i = 0; i < array2.size(); ++i)
184       EXPECT_EQ(static_cast<int32_t>(i), array2[i]);
185   }
186 
Serialization_EmptyArrayOfPOD()187   static void Serialization_EmptyArrayOfPOD() {
188     ArrayType<int32_t> array;
189     size_t size =
190         mojo::internal::PrepareToSerialize<Array<int32_t>>(array, nullptr);
191     EXPECT_EQ(8U, size);
192 
193     mojo::internal::FixedBufferForTesting buf(size);
194     mojo::internal::Array_Data<int32_t>* data;
195     mojo::internal::ContainerValidateParams validate_params(0, false, nullptr);
196     mojo::internal::Serialize<Array<int32_t>>(array, &buf, &data,
197                                               &validate_params, nullptr);
198 
199     ArrayType<int32_t> array2;
200     mojo::internal::Deserialize<Array<int32_t>>(data, &array2, nullptr);
201     EXPECT_EQ(0U, array2.size());
202   }
203 
Serialization_ArrayOfArrayOfPOD()204   static void Serialization_ArrayOfArrayOfPOD() {
205     ArrayType<ArrayType<int32_t>> array(2);
206     for (size_t j = 0; j < array.size(); ++j) {
207       ArrayType<int32_t> inner(4);
208       for (size_t i = 0; i < inner.size(); ++i)
209         inner[i] = static_cast<int32_t>(i + (j * 10));
210       array[j] = std::move(inner);
211     }
212 
213     size_t size = mojo::internal::PrepareToSerialize<Array<Array<int32_t>>>(
214         array, nullptr);
215     EXPECT_EQ(8U + 2 * 8U + 2 * (8U + 4 * 4U), size);
216 
217     mojo::internal::FixedBufferForTesting buf(size);
218     typename mojo::internal::MojomTypeTraits<Array<Array<int32_t>>>::Data* data;
219     mojo::internal::ContainerValidateParams validate_params(
220         0, false,
221         new mojo::internal::ContainerValidateParams(0, false, nullptr));
222     mojo::internal::Serialize<Array<Array<int32_t>>>(array, &buf, &data,
223                                                      &validate_params, nullptr);
224 
225     ArrayType<ArrayType<int32_t>> array2;
226     mojo::internal::Deserialize<Array<Array<int32_t>>>(data, &array2, nullptr);
227 
228     EXPECT_EQ(2U, array2.size());
229     for (size_t j = 0; j < array2.size(); ++j) {
230       const ArrayType<int32_t>& inner = array2[j];
231       EXPECT_EQ(4U, inner.size());
232       for (size_t i = 0; i < inner.size(); ++i)
233         EXPECT_EQ(static_cast<int32_t>(i + (j * 10)), inner[i]);
234     }
235   }
236 
Serialization_ArrayOfBool()237   static void Serialization_ArrayOfBool() {
238     ArrayType<bool> array(10);
239     for (size_t i = 0; i < array.size(); ++i)
240       array[i] = i % 2 ? true : false;
241 
242     size_t size =
243         mojo::internal::PrepareToSerialize<Array<bool>>(array, nullptr);
244     EXPECT_EQ(8U + 8U, size);
245 
246     mojo::internal::FixedBufferForTesting buf(size);
247     mojo::internal::Array_Data<bool>* data;
248     mojo::internal::ContainerValidateParams validate_params(0, false, nullptr);
249     mojo::internal::Serialize<Array<bool>>(array, &buf, &data, &validate_params,
250                                            nullptr);
251 
252     ArrayType<bool> array2;
253     mojo::internal::Deserialize<Array<bool>>(data, &array2, nullptr);
254 
255     EXPECT_EQ(10U, array2.size());
256     for (size_t i = 0; i < array2.size(); ++i)
257       EXPECT_EQ(i % 2 ? true : false, array2[i]);
258   }
259 
Serialization_ArrayOfString()260   static void Serialization_ArrayOfString() {
261     ArrayType<String> array(10);
262     for (size_t i = 0; i < array.size(); ++i) {
263       char c = 'A' + static_cast<char>(i);
264       array[i] = String(&c, 1);
265     }
266 
267     size_t size =
268         mojo::internal::PrepareToSerialize<Array<String>>(array, nullptr);
269     EXPECT_EQ(8U +            // array header
270                   10 * 8U +   // array payload (10 pointers)
271                   10 * (8U +  // string header
272                         8U),  // string length of 1 padded to 8
273               size);
274 
275     mojo::internal::FixedBufferForTesting buf(size);
276     typename mojo::internal::MojomTypeTraits<Array<String>>::Data* data;
277     mojo::internal::ContainerValidateParams validate_params(
278         0, false,
279         new mojo::internal::ContainerValidateParams(0, false, nullptr));
280     mojo::internal::Serialize<Array<String>>(array, &buf, &data,
281                                              &validate_params, nullptr);
282 
283     ArrayType<String> array2;
284     mojo::internal::Deserialize<Array<String>>(data, &array2, nullptr);
285 
286     EXPECT_EQ(10U, array2.size());
287     for (size_t i = 0; i < array2.size(); ++i) {
288       char c = 'A' + static_cast<char>(i);
289       EXPECT_EQ(String(&c, 1), array2[i]);
290     }
291   }
292 
Resize_Copyable()293   static void Resize_Copyable() {
294     ASSERT_EQ(0u, CopyableType::num_instances());
295     ArrayType<CopyableType> array(3);
296     std::vector<CopyableType*> value_ptrs;
297     value_ptrs.push_back(array[0].ptr());
298     value_ptrs.push_back(array[1].ptr());
299 
300     for (size_t i = 0; i < array.size(); i++)
301       array[i].ResetCopied();
302 
303     array.resize(2);
304     ASSERT_EQ(2u, array.size());
305     EXPECT_EQ(array.size(), CopyableType::num_instances());
306     for (size_t i = 0; i < array.size(); i++) {
307       EXPECT_FALSE(array[i].copied());
308       EXPECT_EQ(value_ptrs[i], array[i].ptr());
309     }
310 
311     array.resize(3);
312     array[2].ResetCopied();
313     ASSERT_EQ(3u, array.size());
314     EXPECT_EQ(array.size(), CopyableType::num_instances());
315     for (size_t i = 0; i < array.size(); i++)
316       EXPECT_FALSE(array[i].copied());
317     value_ptrs.push_back(array[2].ptr());
318 
319     size_t capacity = array.storage().capacity();
320     array.resize(capacity);
321     ASSERT_EQ(capacity, array.size());
322     EXPECT_EQ(array.size(), CopyableType::num_instances());
323     for (size_t i = 0; i < 3; i++)
324       EXPECT_FALSE(array[i].copied());
325     for (size_t i = 3; i < array.size(); i++) {
326       array[i].ResetCopied();
327       value_ptrs.push_back(array[i].ptr());
328     }
329 
330     array.resize(capacity + 2);
331     ASSERT_EQ(capacity + 2, array.size());
332     EXPECT_EQ(array.size(), CopyableType::num_instances());
333     for (size_t i = 0; i < capacity; i++) {
334       EXPECT_TRUE(array[i].copied());
335       EXPECT_EQ(value_ptrs[i], array[i].ptr());
336     }
337     array = nullptr;
338     EXPECT_EQ(0u, CopyableType::num_instances());
339     EXPECT_FALSE(array);
340     array.resize(0);
341     EXPECT_EQ(0u, CopyableType::num_instances());
342     EXPECT_TRUE(array);
343   }
344 
Resize_MoveOnly()345   static void Resize_MoveOnly() {
346     ASSERT_EQ(0u, MoveOnlyType::num_instances());
347     ArrayType<MoveOnlyType> array(3);
348     std::vector<MoveOnlyType*> value_ptrs;
349     value_ptrs.push_back(array[0].ptr());
350     value_ptrs.push_back(array[1].ptr());
351 
352     for (size_t i = 0; i < array.size(); i++)
353       EXPECT_FALSE(array[i].moved());
354 
355     array.resize(2);
356     ASSERT_EQ(2u, array.size());
357     EXPECT_EQ(array.size(), MoveOnlyType::num_instances());
358     for (size_t i = 0; i < array.size(); i++) {
359       EXPECT_FALSE(array[i].moved());
360       EXPECT_EQ(value_ptrs[i], array[i].ptr());
361     }
362 
363     array.resize(3);
364     ASSERT_EQ(3u, array.size());
365     EXPECT_EQ(array.size(), MoveOnlyType::num_instances());
366     for (size_t i = 0; i < array.size(); i++)
367       EXPECT_FALSE(array[i].moved());
368     value_ptrs.push_back(array[2].ptr());
369 
370     size_t capacity = array.storage().capacity();
371     array.resize(capacity);
372     ASSERT_EQ(capacity, array.size());
373     EXPECT_EQ(array.size(), MoveOnlyType::num_instances());
374     for (size_t i = 0; i < array.size(); i++)
375       EXPECT_FALSE(array[i].moved());
376     for (size_t i = 3; i < array.size(); i++)
377       value_ptrs.push_back(array[i].ptr());
378 
379     array.resize(capacity + 2);
380     ASSERT_EQ(capacity + 2, array.size());
381     EXPECT_EQ(array.size(), MoveOnlyType::num_instances());
382     for (size_t i = 0; i < capacity; i++) {
383       EXPECT_TRUE(array[i].moved());
384       EXPECT_EQ(value_ptrs[i], array[i].ptr());
385     }
386     for (size_t i = capacity; i < array.size(); i++)
387       EXPECT_FALSE(array[i].moved());
388 
389     array = nullptr;
390     EXPECT_EQ(0u, MoveOnlyType::num_instances());
391     EXPECT_FALSE(array);
392     array.resize(0);
393     EXPECT_EQ(0u, MoveOnlyType::num_instances());
394     EXPECT_TRUE(array);
395   }
396 };
397 
398 #define ARRAY_COMMON_TEST(ArrayType, test_name) \
399   TEST_F(ArrayType##Test, test_name) {          \
400     ArrayCommonTest<ArrayType>::test_name();    \
401   }
402 
403 }  // namespace test
404 }  // namespace mojo
405