• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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