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.
5 #include "mojo/public/cpp/bindings/array.h"
6 #include "mojo/public/cpp/bindings/lib/array_internal.h"
7 #include "mojo/public/cpp/bindings/lib/array_serialization.h"
8 #include "mojo/public/cpp/bindings/lib/fixed_buffer.h"
9 #include "mojo/public/cpp/environment/environment.h"
10 #include "testing/gtest/include/gtest/gtest.h"
18 CopyableType() : copied_(false), ptr_(this) { num_instances_++; }
19 CopyableType(const CopyableType& other) : copied_(true), ptr_(other.ptr()) {
22 CopyableType& operator=(const CopyableType& other) {
27 ~CopyableType() { num_instances_--; }
29 bool copied() const { return copied_; }
30 static size_t num_instances() { return num_instances_; }
31 CopyableType* ptr() const { return ptr_; }
32 void ResetCopied() { copied_ = false; }
36 static size_t num_instances_;
40 size_t CopyableType::num_instances_ = 0;
43 MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(MoveOnlyType, RValue)
45 typedef MoveOnlyType Data_;
46 MoveOnlyType() : moved_(false), ptr_(this) { num_instances_++; }
47 MoveOnlyType(RValue other) : moved_(true), ptr_(other.object->ptr()) {
50 MoveOnlyType& operator=(RValue other) {
52 ptr_ = other.object->ptr();
55 ~MoveOnlyType() { num_instances_--; }
57 bool moved() const { return moved_; }
58 static size_t num_instances() { return num_instances_; }
59 MoveOnlyType* ptr() const { return ptr_; }
60 void ResetMoved() { moved_ = false; }
64 static size_t num_instances_;
68 size_t MoveOnlyType::num_instances_ = 0;
70 class ArrayTest : public testing::Test {
72 virtual ~ArrayTest() {}
78 // Tests that basic Array operations work.
79 TEST_F(ArrayTest, Basic) {
81 for (size_t i = 0; i < array.size(); ++i) {
82 char val = static_cast<char>(i*2);
84 EXPECT_EQ(val, array.at(i));
88 // Tests that basic Array<bool> operations work.
89 TEST_F(ArrayTest, Bool) {
90 Array<bool> array(64);
91 for (size_t i = 0; i < array.size(); ++i) {
92 bool val = i % 3 == 0;
94 EXPECT_EQ(val, array.at(i));
98 // Tests that Array<ScopedMessagePipeHandle> supports transferring handles.
99 TEST_F(ArrayTest, Handle) {
101 Array<ScopedMessagePipeHandle> handles(2);
102 handles[0] = pipe.handle0.Pass();
103 handles[1].reset(pipe.handle1.release());
105 EXPECT_FALSE(pipe.handle0.is_valid());
106 EXPECT_FALSE(pipe.handle1.is_valid());
108 Array<ScopedMessagePipeHandle> handles2 = handles.Pass();
109 EXPECT_TRUE(handles2[0].is_valid());
110 EXPECT_TRUE(handles2[1].is_valid());
112 ScopedMessagePipeHandle pipe_handle = handles2[0].Pass();
113 EXPECT_TRUE(pipe_handle.is_valid());
114 EXPECT_FALSE(handles2[0].is_valid());
117 // Tests that Array<ScopedMessagePipeHandle> supports closing handles.
118 TEST_F(ArrayTest, HandlesAreClosed) {
120 MojoHandle pipe0_value = pipe.handle0.get().value();
121 MojoHandle pipe1_value = pipe.handle0.get().value();
124 Array<ScopedMessagePipeHandle> handles(2);
125 handles[0] = pipe.handle0.Pass();
126 handles[1].reset(pipe.handle0.release());
129 // We expect the pipes to have been closed.
130 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(pipe0_value));
131 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(pipe1_value));
134 TEST_F(ArrayTest, Serialization_ArrayOfPOD) {
135 Array<int32_t> array(4);
136 for (size_t i = 0; i < array.size(); ++i)
137 array[i] = static_cast<int32_t>(i);
139 size_t size = GetSerializedSize_(array);
140 EXPECT_EQ(8U + 4*4U, size);
142 internal::FixedBuffer buf(size);
143 internal::Array_Data<int32_t>* data;
144 SerializeArray_<internal::ArrayValidateParams<0, false,
145 internal::NoValidateParams> >(
146 array.Pass(), &buf, &data);
148 Array<int32_t> array2;
149 Deserialize_(data, &array2);
151 EXPECT_EQ(4U, array2.size());
152 for (size_t i = 0; i < array2.size(); ++i)
153 EXPECT_EQ(static_cast<int32_t>(i), array2[i]);
156 TEST_F(ArrayTest, Serialization_ArrayOfArrayOfPOD) {
157 Array<Array<int32_t> > array(2);
158 for (size_t j = 0; j < array.size(); ++j) {
159 Array<int32_t> inner(4);
160 for (size_t i = 0; i < inner.size(); ++i)
161 inner[i] = static_cast<int32_t>(i + (j * 10));
162 array[j] = inner.Pass();
165 size_t size = GetSerializedSize_(array);
166 EXPECT_EQ(8U + 2*8U + 2*(8U + 4*4U), size);
168 internal::FixedBuffer buf(size);
169 internal::Array_Data<internal::Array_Data<int32_t>*>* data;
170 SerializeArray_<internal::ArrayValidateParams<0, false,
171 internal::ArrayValidateParams<0, false,
172 internal::NoValidateParams> > >(
173 array.Pass(), &buf, &data);
175 Array<Array<int32_t> > array2;
176 Deserialize_(data, &array2);
178 EXPECT_EQ(2U, array2.size());
179 for (size_t j = 0; j < array2.size(); ++j) {
180 const Array<int32_t>& inner = array2[j];
181 EXPECT_EQ(4U, inner.size());
182 for (size_t i = 0; i < inner.size(); ++i)
183 EXPECT_EQ(static_cast<int32_t>(i + (j * 10)), inner[i]);
187 TEST_F(ArrayTest, Serialization_ArrayOfBool) {
188 Array<bool> array(10);
189 for (size_t i = 0; i < array.size(); ++i)
190 array[i] = i % 2 ? true : false;
192 size_t size = GetSerializedSize_(array);
193 EXPECT_EQ(8U + 8U, size);
195 internal::FixedBuffer buf(size);
196 internal::Array_Data<bool>* data;
197 SerializeArray_<internal::ArrayValidateParams<0, false,
198 internal::NoValidateParams> >(
199 array.Pass(), &buf, &data);
202 Deserialize_(data, &array2);
204 EXPECT_EQ(10U, array2.size());
205 for (size_t i = 0; i < array2.size(); ++i)
206 EXPECT_EQ(i % 2 ? true : false, array2[i]);
209 TEST_F(ArrayTest, Serialization_ArrayOfString) {
210 Array<String> array(10);
211 for (size_t i = 0; i < array.size(); ++i) {
212 char c = 'A' + static_cast<char>(i);
213 array[i] = String(&c, 1);
216 size_t size = GetSerializedSize_(array);
217 EXPECT_EQ(8U + // array header
218 10*8U + // array payload (10 pointers)
219 10*(8U + // string header
220 8U), // string length of 1 padded to 8
223 internal::FixedBuffer buf(size);
224 internal::Array_Data<internal::String_Data*>* data;
225 SerializeArray_<internal::ArrayValidateParams<0, false,
226 internal::ArrayValidateParams<0, false,
227 internal::NoValidateParams> > >(
228 array.Pass(), &buf, &data);
230 Array<String> array2;
231 Deserialize_(data, &array2);
233 EXPECT_EQ(10U, array2.size());
234 for (size_t i = 0; i < array2.size(); ++i) {
235 char c = 'A' + static_cast<char>(i);
236 EXPECT_EQ(String(&c, 1), array2[i]);
240 TEST_F(ArrayTest, Resize_Copyable) {
241 ASSERT_EQ(0u, CopyableType::num_instances());
242 mojo::Array<CopyableType> array(3);
243 std::vector<CopyableType*> value_ptrs;
244 value_ptrs.push_back(array[0].ptr());
245 value_ptrs.push_back(array[1].ptr());
247 for (size_t i = 0; i < array.size(); i++)
248 array[i].ResetCopied();
251 ASSERT_EQ(2u, array.size());
252 EXPECT_EQ(array.size(), CopyableType::num_instances());
253 for (size_t i = 0; i < array.size(); i++) {
254 EXPECT_FALSE(array[i].copied());
255 EXPECT_EQ(value_ptrs[i], array[i].ptr());
259 array[2].ResetCopied();
260 ASSERT_EQ(3u, array.size());
261 EXPECT_EQ(array.size(), CopyableType::num_instances());
262 for (size_t i = 0; i < array.size(); i++)
263 EXPECT_FALSE(array[i].copied());
264 value_ptrs.push_back(array[2].ptr());
266 size_t capacity = array.storage().capacity();
267 array.resize(capacity);
268 ASSERT_EQ(capacity, array.size());
269 EXPECT_EQ(array.size(), CopyableType::num_instances());
270 for (size_t i = 0; i < 3; i++)
271 EXPECT_FALSE(array[i].copied());
272 for (size_t i = 3; i < array.size(); i++) {
273 array[i].ResetCopied();
274 value_ptrs.push_back(array[i].ptr());
277 array.resize(capacity + 2);
278 ASSERT_EQ(capacity + 2, array.size());
279 EXPECT_EQ(array.size(), CopyableType::num_instances());
280 for (size_t i = 0; i < capacity; i++) {
281 EXPECT_TRUE(array[i].copied());
282 EXPECT_EQ(value_ptrs[i], array[i].ptr());
285 EXPECT_EQ(0u, CopyableType::num_instances());
288 EXPECT_EQ(0u, CopyableType::num_instances());
292 TEST_F(ArrayTest, Resize_MoveOnly) {
293 ASSERT_EQ(0u, MoveOnlyType::num_instances());
294 mojo::Array<MoveOnlyType> array(3);
295 std::vector<MoveOnlyType*> value_ptrs;
296 value_ptrs.push_back(array[0].ptr());
297 value_ptrs.push_back(array[1].ptr());
299 for (size_t i = 0; i < array.size(); i++)
300 EXPECT_FALSE(array[i].moved());
303 ASSERT_EQ(2u, array.size());
304 EXPECT_EQ(array.size(), MoveOnlyType::num_instances());
305 for (size_t i = 0; i < array.size(); i++) {
306 EXPECT_FALSE(array[i].moved());
307 EXPECT_EQ(value_ptrs[i], array[i].ptr());
311 ASSERT_EQ(3u, array.size());
312 EXPECT_EQ(array.size(), MoveOnlyType::num_instances());
313 for (size_t i = 0; i < array.size(); i++)
314 EXPECT_FALSE(array[i].moved());
315 value_ptrs.push_back(array[2].ptr());
317 size_t capacity = array.storage().capacity();
318 array.resize(capacity);
319 ASSERT_EQ(capacity, array.size());
320 EXPECT_EQ(array.size(), MoveOnlyType::num_instances());
321 for (size_t i = 0; i < array.size(); i++)
322 EXPECT_FALSE(array[i].moved());
323 for (size_t i = 3; i < array.size(); i++)
324 value_ptrs.push_back(array[i].ptr());
326 array.resize(capacity + 2);
327 ASSERT_EQ(capacity + 2, array.size());
328 EXPECT_EQ(array.size(), MoveOnlyType::num_instances());
329 for (size_t i = 0; i < capacity; i++) {
330 EXPECT_TRUE(array[i].moved());
331 EXPECT_EQ(value_ptrs[i], array[i].ptr());
333 for (size_t i = capacity; i < array.size(); i++)
334 EXPECT_FALSE(array[i].moved());
337 EXPECT_EQ(0u, MoveOnlyType::num_instances());
340 EXPECT_EQ(0u, MoveOnlyType::num_instances());
344 TEST_F(ArrayTest, PushBack_Copyable) {
345 ASSERT_EQ(0u, CopyableType::num_instances());
346 mojo::Array<CopyableType> array(2);
348 std::vector<CopyableType*> value_ptrs;
349 size_t capacity = array.storage().capacity();
350 for (size_t i = 0; i < capacity; i++) {
352 value_ptrs.push_back(value.ptr());
353 array.push_back(value);
354 ASSERT_EQ(i + 1, array.size());
355 ASSERT_EQ(i + 1, value_ptrs.size());
356 EXPECT_EQ(array.size() + 1, CopyableType::num_instances());
357 EXPECT_TRUE(array[i].copied());
358 EXPECT_EQ(value_ptrs[i], array[i].ptr());
359 array[i].ResetCopied();
364 value_ptrs.push_back(value.ptr());
365 array.push_back(value);
366 EXPECT_EQ(array.size() + 1, CopyableType::num_instances());
368 ASSERT_EQ(capacity + 1, array.size());
369 EXPECT_EQ(array.size(), CopyableType::num_instances());
371 for (size_t i = 0; i < array.size(); i++) {
372 EXPECT_TRUE(array[i].copied());
373 EXPECT_EQ(value_ptrs[i], array[i].ptr());
376 EXPECT_EQ(0u, CopyableType::num_instances());
379 TEST_F(ArrayTest, PushBack_MoveOnly) {
380 ASSERT_EQ(0u, MoveOnlyType::num_instances());
381 mojo::Array<MoveOnlyType> array(2);
383 std::vector<MoveOnlyType*> value_ptrs;
384 size_t capacity = array.storage().capacity();
385 for (size_t i = 0; i < capacity; i++) {
387 value_ptrs.push_back(value.ptr());
388 array.push_back(value.Pass());
389 ASSERT_EQ(i + 1, array.size());
390 ASSERT_EQ(i + 1, value_ptrs.size());
391 EXPECT_EQ(array.size() + 1, MoveOnlyType::num_instances());
392 EXPECT_TRUE(array[i].moved());
393 EXPECT_EQ(value_ptrs[i], array[i].ptr());
394 array[i].ResetMoved();
399 value_ptrs.push_back(value.ptr());
400 array.push_back(value.Pass());
401 EXPECT_EQ(array.size() + 1, MoveOnlyType::num_instances());
403 ASSERT_EQ(capacity + 1, array.size());
404 EXPECT_EQ(array.size(), MoveOnlyType::num_instances());
406 for (size_t i = 0; i < array.size(); i++) {
407 EXPECT_TRUE(array[i].moved());
408 EXPECT_EQ(value_ptrs[i], array[i].ptr());
411 EXPECT_EQ(0u, MoveOnlyType::num_instances());