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 "mojo/public/cpp/bindings/array.h"
6 #include "mojo/public/cpp/bindings/lib/array_serialization.h"
7 #include "mojo/public/cpp/bindings/lib/fixed_buffer.h"
8 #include "mojo/public/cpp/environment/environment.h"
9 #include "mojo/public/interfaces/bindings/tests/sample_service.mojom.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11
12 namespace mojo {
13 namespace test {
14 namespace {
15
16 class CopyableType {
17 public:
CopyableType()18 CopyableType() : copied_(false), ptr_(this) { num_instances_++; }
CopyableType(const CopyableType & other)19 CopyableType(const CopyableType& other) : copied_(true), ptr_(other.ptr()) {
20 num_instances_++;
21 }
operator =(const CopyableType & other)22 CopyableType& operator=(const CopyableType& other) {
23 copied_ = true;
24 ptr_ = other.ptr();
25 return *this;
26 }
~CopyableType()27 ~CopyableType() { num_instances_--; }
28
copied() const29 bool copied() const { return copied_; }
num_instances()30 static size_t num_instances() { return num_instances_; }
ptr() const31 CopyableType* ptr() const { return ptr_; }
ResetCopied()32 void ResetCopied() { copied_ = false; }
33
34 private:
35 bool copied_;
36 static size_t num_instances_;
37 CopyableType* ptr_;
38 };
39
40 size_t CopyableType::num_instances_ = 0;
41
42 class MoveOnlyType {
43 MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(MoveOnlyType, RValue)
44 public:
45 typedef MoveOnlyType Data_;
MoveOnlyType()46 MoveOnlyType() : moved_(false), ptr_(this) { num_instances_++; }
MoveOnlyType(RValue other)47 MoveOnlyType(RValue other) : moved_(true), ptr_(other.object->ptr()) {
48 num_instances_++;
49 }
operator =(RValue other)50 MoveOnlyType& operator=(RValue other) {
51 moved_ = true;
52 ptr_ = other.object->ptr();
53 return *this;
54 }
~MoveOnlyType()55 ~MoveOnlyType() { num_instances_--; }
56
moved() const57 bool moved() const { return moved_; }
num_instances()58 static size_t num_instances() { return num_instances_; }
ptr() const59 MoveOnlyType* ptr() const { return ptr_; }
ResetMoved()60 void ResetMoved() { moved_ = false; }
61
62 private:
63 bool moved_;
64 static size_t num_instances_;
65 MoveOnlyType* ptr_;
66 };
67
68 size_t MoveOnlyType::num_instances_ = 0;
69
70 // Tests that basic Array operations work.
TEST(ArrayTest,Basic)71 TEST(ArrayTest, Basic) {
72 Array<char> array(8);
73 for (size_t i = 0; i < array.size(); ++i) {
74 char val = static_cast<char>(i*2);
75 array[i] = val;
76 EXPECT_EQ(val, array.at(i));
77 }
78 }
79
80 // Tests that basic Array<bool> operations work.
TEST(ArrayTest,Bool)81 TEST(ArrayTest, Bool) {
82 Array<bool> array(64);
83 for (size_t i = 0; i < array.size(); ++i) {
84 bool val = i % 3 == 0;
85 array[i] = val;
86 EXPECT_EQ(val, array.at(i));
87 }
88 }
89
90 // Tests that Array<ScopedMessagePipeHandle> supports transferring handles.
TEST(ArrayTest,Handle)91 TEST(ArrayTest, Handle) {
92 MessagePipe pipe;
93 Array<ScopedMessagePipeHandle> handles(2);
94 handles[0] = pipe.handle0.Pass();
95 handles[1].reset(pipe.handle1.release());
96
97 EXPECT_FALSE(pipe.handle0.is_valid());
98 EXPECT_FALSE(pipe.handle1.is_valid());
99
100 Array<ScopedMessagePipeHandle> handles2 = handles.Pass();
101 EXPECT_TRUE(handles2[0].is_valid());
102 EXPECT_TRUE(handles2[1].is_valid());
103
104 ScopedMessagePipeHandle pipe_handle = handles2[0].Pass();
105 EXPECT_TRUE(pipe_handle.is_valid());
106 EXPECT_FALSE(handles2[0].is_valid());
107 }
108
109 // Tests that Array<ScopedMessagePipeHandle> supports closing handles.
TEST(ArrayTest,HandlesAreClosed)110 TEST(ArrayTest, HandlesAreClosed) {
111 MessagePipe pipe;
112 MojoHandle pipe0_value = pipe.handle0.get().value();
113 MojoHandle pipe1_value = pipe.handle0.get().value();
114
115 {
116 Array<ScopedMessagePipeHandle> handles(2);
117 handles[0] = pipe.handle0.Pass();
118 handles[1].reset(pipe.handle0.release());
119 }
120
121 // We expect the pipes to have been closed.
122 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(pipe0_value));
123 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(pipe1_value));
124 }
125
TEST(ArrayTest,Serialization_ArrayOfPOD)126 TEST(ArrayTest, Serialization_ArrayOfPOD) {
127 Array<int32_t> array(4);
128 for (size_t i = 0; i < array.size(); ++i)
129 array[i] = static_cast<int32_t>(i);
130
131 size_t size = GetSerializedSize_(array);
132 EXPECT_EQ(8U + 4*4U, size);
133
134 internal::FixedBuffer buf(size);
135 internal::Array_Data<int32_t>* data;
136 Serialize_(array.Pass(), &buf, &data);
137
138 Array<int32_t> array2;
139 Deserialize_(data, &array2);
140
141 EXPECT_EQ(4U, array2.size());
142 for (size_t i = 0; i < array2.size(); ++i)
143 EXPECT_EQ(static_cast<int32_t>(i), array2[i]);
144 }
145
TEST(ArrayTest,Serialization_ArrayOfArrayOfPOD)146 TEST(ArrayTest, Serialization_ArrayOfArrayOfPOD) {
147 Array<Array<int32_t> > array(2);
148 for (size_t j = 0; j < array.size(); ++j) {
149 Array<int32_t> inner(4);
150 for (size_t i = 0; i < inner.size(); ++i)
151 inner[i] = static_cast<int32_t>(i + (j * 10));
152 array[j] = inner.Pass();
153 }
154
155 size_t size = GetSerializedSize_(array);
156 EXPECT_EQ(8U + 2*8U + 2*(8U + 4*4U), size);
157
158 internal::FixedBuffer buf(size);
159 internal::Array_Data<internal::Array_Data<int32_t>*>* data;
160 Serialize_(array.Pass(), &buf, &data);
161
162 Array<Array<int32_t> > array2;
163 Deserialize_(data, &array2);
164
165 EXPECT_EQ(2U, array2.size());
166 for (size_t j = 0; j < array2.size(); ++j) {
167 const Array<int32_t>& inner = array2[j];
168 EXPECT_EQ(4U, inner.size());
169 for (size_t i = 0; i < inner.size(); ++i)
170 EXPECT_EQ(static_cast<int32_t>(i + (j * 10)), inner[i]);
171 }
172 }
173
TEST(ArrayTest,Serialization_ArrayOfBool)174 TEST(ArrayTest, Serialization_ArrayOfBool) {
175 Array<bool> array(10);
176 for (size_t i = 0; i < array.size(); ++i)
177 array[i] = i % 2 ? true : false;
178
179 size_t size = GetSerializedSize_(array);
180 EXPECT_EQ(8U + 8U, size);
181
182 internal::FixedBuffer buf(size);
183 internal::Array_Data<bool>* data;
184 Serialize_(array.Pass(), &buf, &data);
185
186 Array<bool> array2;
187 Deserialize_(data, &array2);
188
189 EXPECT_EQ(10U, array2.size());
190 for (size_t i = 0; i < array2.size(); ++i)
191 EXPECT_EQ(i % 2 ? true : false, array2[i]);
192 }
193
TEST(ArrayTest,Serialization_ArrayOfString)194 TEST(ArrayTest, Serialization_ArrayOfString) {
195 Array<String> array(10);
196 for (size_t i = 0; i < array.size(); ++i) {
197 char c = 'A' + 1;
198 array[i] = String(&c, 1);
199 }
200
201 size_t size = GetSerializedSize_(array);
202 EXPECT_EQ(8U + // array header
203 10*8U + // array payload (10 pointers)
204 10*(8U + // string header
205 8U), // string length of 1 padded to 8
206 size);
207
208 internal::FixedBuffer buf(size);
209 internal::Array_Data<internal::String_Data*>* data;
210 Serialize_(array.Pass(), &buf, &data);
211
212 Array<String> array2;
213 Deserialize_(data, &array2);
214
215 EXPECT_EQ(10U, array2.size());
216 for (size_t i = 0; i < array2.size(); ++i) {
217 char c = 'A' + 1;
218 EXPECT_EQ(String(&c, 1), array2[i]);
219 }
220 }
221
TEST(ArrayTest,Resize_Copyable)222 TEST(ArrayTest, Resize_Copyable) {
223 ASSERT_EQ(0u, CopyableType::num_instances());
224 mojo::Array<CopyableType> array(3);
225 std::vector<CopyableType*> value_ptrs;
226 value_ptrs.push_back(array[0].ptr());
227 value_ptrs.push_back(array[1].ptr());
228
229 for (size_t i = 0; i < array.size(); i++)
230 array[i].ResetCopied();
231
232 array.resize(2);
233 ASSERT_EQ(2u, array.size());
234 EXPECT_EQ(array.size(), CopyableType::num_instances());
235 for (size_t i = 0; i < array.size(); i++) {
236 EXPECT_FALSE(array[i].copied());
237 EXPECT_EQ(value_ptrs[i], array[i].ptr());
238 }
239
240 array.resize(3);
241 array[2].ResetCopied();
242 ASSERT_EQ(3u, array.size());
243 EXPECT_EQ(array.size(), CopyableType::num_instances());
244 for (size_t i = 0; i < array.size(); i++)
245 EXPECT_FALSE(array[i].copied());
246 value_ptrs.push_back(array[2].ptr());
247
248 size_t capacity = array.storage().capacity();
249 array.resize(capacity);
250 ASSERT_EQ(capacity, array.size());
251 EXPECT_EQ(array.size(), CopyableType::num_instances());
252 for (size_t i = 0; i < 3; i++)
253 EXPECT_FALSE(array[i].copied());
254 for (size_t i = 3; i < array.size(); i++) {
255 array[i].ResetCopied();
256 value_ptrs.push_back(array[i].ptr());
257 }
258
259 array.resize(capacity + 2);
260 ASSERT_EQ(capacity + 2, array.size());
261 EXPECT_EQ(array.size(), CopyableType::num_instances());
262 for (size_t i = 0; i < capacity; i++) {
263 EXPECT_TRUE(array[i].copied());
264 EXPECT_EQ(value_ptrs[i], array[i].ptr());
265 }
266 array.reset();
267 EXPECT_EQ(0u, CopyableType::num_instances());
268 EXPECT_FALSE(array);
269 array.resize(0);
270 EXPECT_EQ(0u, CopyableType::num_instances());
271 EXPECT_TRUE(array);
272 }
273
TEST(ArrayTest,Resize_MoveOnly)274 TEST(ArrayTest, Resize_MoveOnly) {
275 ASSERT_EQ(0u, MoveOnlyType::num_instances());
276 mojo::Array<MoveOnlyType> array(3);
277 std::vector<MoveOnlyType*> value_ptrs;
278 value_ptrs.push_back(array[0].ptr());
279 value_ptrs.push_back(array[1].ptr());
280
281 for (size_t i = 0; i < array.size(); i++)
282 EXPECT_FALSE(array[i].moved());
283
284 array.resize(2);
285 ASSERT_EQ(2u, array.size());
286 EXPECT_EQ(array.size(), MoveOnlyType::num_instances());
287 for (size_t i = 0; i < array.size(); i++) {
288 EXPECT_FALSE(array[i].moved());
289 EXPECT_EQ(value_ptrs[i], array[i].ptr());
290 }
291
292 array.resize(3);
293 ASSERT_EQ(3u, array.size());
294 EXPECT_EQ(array.size(), MoveOnlyType::num_instances());
295 for (size_t i = 0; i < array.size(); i++)
296 EXPECT_FALSE(array[i].moved());
297 value_ptrs.push_back(array[2].ptr());
298
299 size_t capacity = array.storage().capacity();
300 array.resize(capacity);
301 ASSERT_EQ(capacity, array.size());
302 EXPECT_EQ(array.size(), MoveOnlyType::num_instances());
303 for (size_t i = 0; i < array.size(); i++)
304 EXPECT_FALSE(array[i].moved());
305 for (size_t i = 3; i < array.size(); i++)
306 value_ptrs.push_back(array[i].ptr());
307
308 array.resize(capacity + 2);
309 ASSERT_EQ(capacity + 2, array.size());
310 EXPECT_EQ(array.size(), MoveOnlyType::num_instances());
311 for (size_t i = 0; i < capacity; i++) {
312 EXPECT_TRUE(array[i].moved());
313 EXPECT_EQ(value_ptrs[i], array[i].ptr());
314 }
315 for (size_t i = capacity; i < array.size(); i++)
316 EXPECT_FALSE(array[i].moved());
317
318 array.reset();
319 EXPECT_EQ(0u, MoveOnlyType::num_instances());
320 EXPECT_FALSE(array);
321 array.resize(0);
322 EXPECT_EQ(0u, MoveOnlyType::num_instances());
323 EXPECT_TRUE(array);
324 }
325
TEST(ArrayTest,PushBack_Copyable)326 TEST(ArrayTest, PushBack_Copyable) {
327 ASSERT_EQ(0u, CopyableType::num_instances());
328 mojo::Array<CopyableType> array(2);
329 array.reset();
330 std::vector<CopyableType*> value_ptrs;
331 size_t capacity = array.storage().capacity();
332 for (size_t i = 0; i < capacity; i++) {
333 CopyableType value;
334 value_ptrs.push_back(value.ptr());
335 array.push_back(value);
336 ASSERT_EQ(i + 1, array.size());
337 ASSERT_EQ(i + 1, value_ptrs.size());
338 EXPECT_EQ(array.size() + 1, CopyableType::num_instances());
339 EXPECT_TRUE(array[i].copied());
340 EXPECT_EQ(value_ptrs[i], array[i].ptr());
341 array[i].ResetCopied();
342 EXPECT_TRUE(array);
343 }
344 {
345 CopyableType value;
346 value_ptrs.push_back(value.ptr());
347 array.push_back(value);
348 EXPECT_EQ(array.size() + 1, CopyableType::num_instances());
349 }
350 ASSERT_EQ(capacity + 1, array.size());
351 EXPECT_EQ(array.size(), CopyableType::num_instances());
352
353 for (size_t i = 0; i < array.size(); i++) {
354 EXPECT_TRUE(array[i].copied());
355 EXPECT_EQ(value_ptrs[i], array[i].ptr());
356 }
357 array.reset();
358 EXPECT_EQ(0u, CopyableType::num_instances());
359 }
360
TEST(ArrayTest,PushBack_MoveOnly)361 TEST(ArrayTest, PushBack_MoveOnly) {
362 ASSERT_EQ(0u, MoveOnlyType::num_instances());
363 mojo::Array<MoveOnlyType> array(2);
364 array.reset();
365 std::vector<MoveOnlyType*> value_ptrs;
366 size_t capacity = array.storage().capacity();
367 for (size_t i = 0; i < capacity; i++) {
368 MoveOnlyType value;
369 value_ptrs.push_back(value.ptr());
370 array.push_back(value.Pass());
371 ASSERT_EQ(i + 1, array.size());
372 ASSERT_EQ(i + 1, value_ptrs.size());
373 EXPECT_EQ(array.size() + 1, MoveOnlyType::num_instances());
374 EXPECT_TRUE(array[i].moved());
375 EXPECT_EQ(value_ptrs[i], array[i].ptr());
376 array[i].ResetMoved();
377 EXPECT_TRUE(array);
378 }
379 {
380 MoveOnlyType value;
381 value_ptrs.push_back(value.ptr());
382 array.push_back(value.Pass());
383 EXPECT_EQ(array.size() + 1, MoveOnlyType::num_instances());
384 }
385 ASSERT_EQ(capacity + 1, array.size());
386 EXPECT_EQ(array.size(), MoveOnlyType::num_instances());
387
388 for (size_t i = 0; i < array.size(); i++) {
389 EXPECT_TRUE(array[i].moved());
390 EXPECT_EQ(value_ptrs[i], array[i].ptr());
391 }
392 array.reset();
393 EXPECT_EQ(0u, MoveOnlyType::num_instances());
394 }
395
396 } // namespace
397 } // namespace test
398 } // namespace mojo
399