• 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 <stddef.h>
6 #include <stdint.h>
7 #include <string.h>
8 #include <utility>
9 
10 #include "mojo/public/cpp/bindings/lib/fixed_buffer.h"
11 #include "mojo/public/cpp/system/message_pipe.h"
12 #include "mojo/public/interfaces/bindings/tests/test_structs.mojom.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 
15 namespace mojo {
16 namespace test {
17 namespace {
18 
MakeRect(int32_t factor=1)19 RectPtr MakeRect(int32_t factor = 1) {
20   RectPtr rect(Rect::New());
21   rect->x = 1 * factor;
22   rect->y = 2 * factor;
23   rect->width = 10 * factor;
24   rect->height = 20 * factor;
25   return rect;
26 }
27 
CheckRect(const Rect & rect,int32_t factor=1)28 void CheckRect(const Rect& rect, int32_t factor = 1) {
29   EXPECT_EQ(1 * factor, rect.x);
30   EXPECT_EQ(2 * factor, rect.y);
31   EXPECT_EQ(10 * factor, rect.width);
32   EXPECT_EQ(20 * factor, rect.height);
33 }
34 
MakeMultiVersionStruct()35 MultiVersionStructPtr MakeMultiVersionStruct() {
36   MultiVersionStructPtr output(MultiVersionStruct::New());
37   output->f_int32 = 123;
38   output->f_rect = MakeRect(5);
39   output->f_string.emplace("hello");
40   output->f_array.emplace(3);
41   (*output->f_array)[0] = 10;
42   (*output->f_array)[1] = 9;
43   (*output->f_array)[2] = 8;
44   MessagePipe pipe;
45   output->f_message_pipe = std::move(pipe.handle0);
46   output->f_int16 = 42;
47 
48   return output;
49 }
50 
51 template <typename U, typename T>
SerializeAndDeserialize(T input)52 U SerializeAndDeserialize(T input) {
53   using InputDataType = typename mojo::internal::MojomTypeTraits<T>::Data*;
54   using OutputDataType = typename mojo::internal::MojomTypeTraits<U>::Data*;
55 
56   mojo::internal::SerializationContext context;
57   size_t size = mojo::internal::PrepareToSerialize<T>(input, &context);
58   mojo::internal::FixedBufferForTesting buf(size + 32);
59   InputDataType data;
60   mojo::internal::Serialize<T>(input, &buf, &data, &context);
61 
62   // Set the subsequent area to a special value, so that we can find out if we
63   // mistakenly access the area.
64   void* subsequent_area = buf.Allocate(32);
65   memset(subsequent_area, 0xAA, 32);
66 
67   OutputDataType output_data = reinterpret_cast<OutputDataType>(data);
68 
69   U output;
70   mojo::internal::Deserialize<U>(output_data, &output, &context);
71   return std::move(output);
72 }
73 
74 using StructTest = testing::Test;
75 
76 }  // namespace
77 
TEST_F(StructTest,Rect)78 TEST_F(StructTest, Rect) {
79   RectPtr rect;
80   EXPECT_TRUE(rect.is_null());
81   EXPECT_TRUE(!rect);
82   EXPECT_FALSE(rect);
83 
84   rect = nullptr;
85   EXPECT_TRUE(rect.is_null());
86   EXPECT_TRUE(!rect);
87   EXPECT_FALSE(rect);
88 
89   rect = MakeRect();
90   EXPECT_FALSE(rect.is_null());
91   EXPECT_FALSE(!rect);
92   EXPECT_TRUE(rect);
93 
94   RectPtr null_rect = nullptr;
95   EXPECT_TRUE(null_rect.is_null());
96   EXPECT_TRUE(!null_rect);
97   EXPECT_FALSE(null_rect);
98 
99   CheckRect(*rect);
100 }
101 
TEST_F(StructTest,Clone)102 TEST_F(StructTest, Clone) {
103   NamedRegionPtr region;
104 
105   NamedRegionPtr clone_region = region.Clone();
106   EXPECT_TRUE(clone_region.is_null());
107 
108   region = NamedRegion::New();
109   clone_region = region.Clone();
110   EXPECT_FALSE(clone_region->name);
111   EXPECT_FALSE(clone_region->rects);
112 
113   region->name.emplace("hello world");
114   clone_region = region.Clone();
115   EXPECT_EQ(region->name, clone_region->name);
116 
117   region->rects.emplace(2);
118   (*region->rects)[1] = MakeRect();
119   clone_region = region.Clone();
120   EXPECT_EQ(2u, clone_region->rects->size());
121   EXPECT_TRUE((*clone_region->rects)[0].is_null());
122   CheckRect(*(*clone_region->rects)[1]);
123 
124   // NoDefaultFieldValues contains handles, so Clone() is not available, but
125   // NoDefaultFieldValuesPtr should still compile.
126   NoDefaultFieldValuesPtr no_default_field_values(NoDefaultFieldValues::New());
127   EXPECT_FALSE(no_default_field_values->f13.is_valid());
128 }
129 
130 // Serialization test of a struct with no pointer or handle members.
TEST_F(StructTest,Serialization_Basic)131 TEST_F(StructTest, Serialization_Basic) {
132   RectPtr rect(MakeRect());
133 
134   size_t size = mojo::internal::PrepareToSerialize<RectPtr>(rect, nullptr);
135   EXPECT_EQ(8U + 16U, size);
136 
137   mojo::internal::FixedBufferForTesting buf(size);
138   internal::Rect_Data* data;
139   mojo::internal::Serialize<RectPtr>(rect, &buf, &data, nullptr);
140 
141   RectPtr rect2;
142   mojo::internal::Deserialize<RectPtr>(data, &rect2, nullptr);
143 
144   CheckRect(*rect2);
145 }
146 
147 // Construction of a struct with struct pointers from null.
TEST_F(StructTest,Construction_StructPointers)148 TEST_F(StructTest, Construction_StructPointers) {
149   RectPairPtr pair;
150   EXPECT_TRUE(pair.is_null());
151 
152   pair = RectPair::New();
153   EXPECT_FALSE(pair.is_null());
154   EXPECT_TRUE(pair->first.is_null());
155   EXPECT_TRUE(pair->first.is_null());
156 
157   pair = nullptr;
158   EXPECT_TRUE(pair.is_null());
159 }
160 
161 // Serialization test of a struct with struct pointers.
TEST_F(StructTest,Serialization_StructPointers)162 TEST_F(StructTest, Serialization_StructPointers) {
163   RectPairPtr pair(RectPair::New());
164   pair->first = MakeRect();
165   pair->second = MakeRect();
166 
167   size_t size = mojo::internal::PrepareToSerialize<RectPairPtr>(pair, nullptr);
168   EXPECT_EQ(8U + 16U + 2 * (8U + 16U), size);
169 
170   mojo::internal::FixedBufferForTesting buf(size);
171   internal::RectPair_Data* data;
172   mojo::internal::Serialize<RectPairPtr>(pair, &buf, &data, nullptr);
173 
174   RectPairPtr pair2;
175   mojo::internal::Deserialize<RectPairPtr>(data, &pair2, nullptr);
176 
177   CheckRect(*pair2->first);
178   CheckRect(*pair2->second);
179 }
180 
181 // Serialization test of a struct with an array member.
TEST_F(StructTest,Serialization_ArrayPointers)182 TEST_F(StructTest, Serialization_ArrayPointers) {
183   NamedRegionPtr region(NamedRegion::New());
184   region->name.emplace("region");
185   region->rects.emplace(4);
186   for (size_t i = 0; i < region->rects->size(); ++i)
187     (*region->rects)[i] = MakeRect(static_cast<int32_t>(i) + 1);
188 
189   size_t size =
190       mojo::internal::PrepareToSerialize<NamedRegionPtr>(region, nullptr);
191   EXPECT_EQ(8U +            // header
192                 8U +        // name pointer
193                 8U +        // rects pointer
194                 8U +        // name header
195                 8U +        // name payload (rounded up)
196                 8U +        // rects header
197                 4 * 8U +    // rects payload (four pointers)
198                 4 * (8U +   // rect header
199                      16U),  // rect payload (four ints)
200             size);
201 
202   mojo::internal::FixedBufferForTesting buf(size);
203   internal::NamedRegion_Data* data;
204   mojo::internal::Serialize<NamedRegionPtr>(region, &buf, &data, nullptr);
205 
206   NamedRegionPtr region2;
207   mojo::internal::Deserialize<NamedRegionPtr>(data, &region2, nullptr);
208 
209   EXPECT_EQ("region", *region2->name);
210 
211   EXPECT_EQ(4U, region2->rects->size());
212   for (size_t i = 0; i < region2->rects->size(); ++i)
213     CheckRect(*(*region2->rects)[i], static_cast<int32_t>(i) + 1);
214 }
215 
216 // Serialization test of a struct with null array pointers.
TEST_F(StructTest,Serialization_NullArrayPointers)217 TEST_F(StructTest, Serialization_NullArrayPointers) {
218   NamedRegionPtr region(NamedRegion::New());
219   EXPECT_FALSE(region->name);
220   EXPECT_FALSE(region->rects);
221 
222   size_t size =
223       mojo::internal::PrepareToSerialize<NamedRegionPtr>(region, nullptr);
224   EXPECT_EQ(8U +      // header
225                 8U +  // name pointer
226                 8U,   // rects pointer
227             size);
228 
229   mojo::internal::FixedBufferForTesting buf(size);
230   internal::NamedRegion_Data* data;
231   mojo::internal::Serialize<NamedRegionPtr>(region, &buf, &data, nullptr);
232 
233   NamedRegionPtr region2;
234   mojo::internal::Deserialize<NamedRegionPtr>(data, &region2, nullptr);
235 
236   EXPECT_FALSE(region2->name);
237   EXPECT_FALSE(region2->rects);
238 }
239 
240 // Tests deserializing structs as a newer version.
TEST_F(StructTest,Versioning_OldToNew)241 TEST_F(StructTest, Versioning_OldToNew) {
242   {
243     MultiVersionStructV0Ptr input(MultiVersionStructV0::New());
244     input->f_int32 = 123;
245     MultiVersionStructPtr expected_output(MultiVersionStruct::New());
246     expected_output->f_int32 = 123;
247 
248     MultiVersionStructPtr output =
249         SerializeAndDeserialize<MultiVersionStructPtr>(std::move(input));
250     EXPECT_TRUE(output);
251     EXPECT_TRUE(output->Equals(*expected_output));
252   }
253 
254   {
255     MultiVersionStructV1Ptr input(MultiVersionStructV1::New());
256     input->f_int32 = 123;
257     input->f_rect = MakeRect(5);
258     MultiVersionStructPtr expected_output(MultiVersionStruct::New());
259     expected_output->f_int32 = 123;
260     expected_output->f_rect = MakeRect(5);
261 
262     MultiVersionStructPtr output =
263         SerializeAndDeserialize<MultiVersionStructPtr>(std::move(input));
264     EXPECT_TRUE(output);
265     EXPECT_TRUE(output->Equals(*expected_output));
266   }
267 
268   {
269     MultiVersionStructV3Ptr input(MultiVersionStructV3::New());
270     input->f_int32 = 123;
271     input->f_rect = MakeRect(5);
272     input->f_string.emplace("hello");
273     MultiVersionStructPtr expected_output(MultiVersionStruct::New());
274     expected_output->f_int32 = 123;
275     expected_output->f_rect = MakeRect(5);
276     expected_output->f_string.emplace("hello");
277 
278     MultiVersionStructPtr output =
279         SerializeAndDeserialize<MultiVersionStructPtr>(std::move(input));
280     EXPECT_TRUE(output);
281     EXPECT_TRUE(output->Equals(*expected_output));
282   }
283 
284   {
285     MultiVersionStructV5Ptr input(MultiVersionStructV5::New());
286     input->f_int32 = 123;
287     input->f_rect = MakeRect(5);
288     input->f_string.emplace("hello");
289     input->f_array.emplace(3);
290     (*input->f_array)[0] = 10;
291     (*input->f_array)[1] = 9;
292     (*input->f_array)[2] = 8;
293     MultiVersionStructPtr expected_output(MultiVersionStruct::New());
294     expected_output->f_int32 = 123;
295     expected_output->f_rect = MakeRect(5);
296     expected_output->f_string.emplace("hello");
297     expected_output->f_array.emplace(3);
298     (*expected_output->f_array)[0] = 10;
299     (*expected_output->f_array)[1] = 9;
300     (*expected_output->f_array)[2] = 8;
301 
302     MultiVersionStructPtr output =
303         SerializeAndDeserialize<MultiVersionStructPtr>(std::move(input));
304     EXPECT_TRUE(output);
305     EXPECT_TRUE(output->Equals(*expected_output));
306   }
307 
308   {
309     MultiVersionStructV7Ptr input(MultiVersionStructV7::New());
310     input->f_int32 = 123;
311     input->f_rect = MakeRect(5);
312     input->f_string.emplace("hello");
313     input->f_array.emplace(3);
314     (*input->f_array)[0] = 10;
315     (*input->f_array)[1] = 9;
316     (*input->f_array)[2] = 8;
317     MessagePipe pipe;
318     input->f_message_pipe = std::move(pipe.handle0);
319 
320     MultiVersionStructPtr expected_output(MultiVersionStruct::New());
321     expected_output->f_int32 = 123;
322     expected_output->f_rect = MakeRect(5);
323     expected_output->f_string.emplace("hello");
324     expected_output->f_array.emplace(3);
325     (*expected_output->f_array)[0] = 10;
326     (*expected_output->f_array)[1] = 9;
327     (*expected_output->f_array)[2] = 8;
328     // Save the raw handle value separately so that we can compare later.
329     MojoHandle expected_handle = input->f_message_pipe.get().value();
330 
331     MultiVersionStructPtr output =
332         SerializeAndDeserialize<MultiVersionStructPtr>(std::move(input));
333     EXPECT_TRUE(output);
334     EXPECT_EQ(expected_handle, output->f_message_pipe.get().value());
335     output->f_message_pipe.reset();
336     EXPECT_TRUE(output->Equals(*expected_output));
337   }
338 }
339 
340 // Tests deserializing structs as an older version.
TEST_F(StructTest,Versioning_NewToOld)341 TEST_F(StructTest, Versioning_NewToOld) {
342   {
343     MultiVersionStructPtr input = MakeMultiVersionStruct();
344     MultiVersionStructV7Ptr expected_output(MultiVersionStructV7::New());
345     expected_output->f_int32 = 123;
346     expected_output->f_rect = MakeRect(5);
347     expected_output->f_string.emplace("hello");
348     expected_output->f_array.emplace(3);
349     (*expected_output->f_array)[0] = 10;
350     (*expected_output->f_array)[1] = 9;
351     (*expected_output->f_array)[2] = 8;
352     // Save the raw handle value separately so that we can compare later.
353     MojoHandle expected_handle = input->f_message_pipe.get().value();
354 
355     MultiVersionStructV7Ptr output =
356         SerializeAndDeserialize<MultiVersionStructV7Ptr>(std::move(input));
357     EXPECT_TRUE(output);
358     EXPECT_EQ(expected_handle, output->f_message_pipe.get().value());
359     output->f_message_pipe.reset();
360     EXPECT_TRUE(output->Equals(*expected_output));
361   }
362 
363   {
364     MultiVersionStructPtr input = MakeMultiVersionStruct();
365     MultiVersionStructV5Ptr expected_output(MultiVersionStructV5::New());
366     expected_output->f_int32 = 123;
367     expected_output->f_rect = MakeRect(5);
368     expected_output->f_string.emplace("hello");
369     expected_output->f_array.emplace(3);
370     (*expected_output->f_array)[0] = 10;
371     (*expected_output->f_array)[1] = 9;
372     (*expected_output->f_array)[2] = 8;
373 
374     MultiVersionStructV5Ptr output =
375         SerializeAndDeserialize<MultiVersionStructV5Ptr>(std::move(input));
376     EXPECT_TRUE(output);
377     EXPECT_TRUE(output->Equals(*expected_output));
378   }
379 
380   {
381     MultiVersionStructPtr input = MakeMultiVersionStruct();
382     MultiVersionStructV3Ptr expected_output(MultiVersionStructV3::New());
383     expected_output->f_int32 = 123;
384     expected_output->f_rect = MakeRect(5);
385     expected_output->f_string.emplace("hello");
386 
387     MultiVersionStructV3Ptr output =
388         SerializeAndDeserialize<MultiVersionStructV3Ptr>(std::move(input));
389     EXPECT_TRUE(output);
390     EXPECT_TRUE(output->Equals(*expected_output));
391   }
392 
393   {
394     MultiVersionStructPtr input = MakeMultiVersionStruct();
395     MultiVersionStructV1Ptr expected_output(MultiVersionStructV1::New());
396     expected_output->f_int32 = 123;
397     expected_output->f_rect = MakeRect(5);
398 
399     MultiVersionStructV1Ptr output =
400         SerializeAndDeserialize<MultiVersionStructV1Ptr>(std::move(input));
401     EXPECT_TRUE(output);
402     EXPECT_TRUE(output->Equals(*expected_output));
403   }
404 
405   {
406     MultiVersionStructPtr input = MakeMultiVersionStruct();
407     MultiVersionStructV0Ptr expected_output(MultiVersionStructV0::New());
408     expected_output->f_int32 = 123;
409 
410     MultiVersionStructV0Ptr output =
411         SerializeAndDeserialize<MultiVersionStructV0Ptr>(std::move(input));
412     EXPECT_TRUE(output);
413     EXPECT_TRUE(output->Equals(*expected_output));
414   }
415 }
416 
417 // Serialization test for native struct.
TEST_F(StructTest,Serialization_NativeStruct)418 TEST_F(StructTest, Serialization_NativeStruct) {
419   using Data = mojo::internal::NativeStruct_Data;
420   {
421     // Serialization of a null native struct.
422     NativeStructPtr native;
423     size_t size =
424         mojo::internal::PrepareToSerialize<NativeStructPtr>(native, nullptr);
425     EXPECT_EQ(0u, size);
426     mojo::internal::FixedBufferForTesting buf(size);
427 
428     Data* data = nullptr;
429     mojo::internal::Serialize<NativeStructPtr>(std::move(native), &buf, &data,
430                                                nullptr);
431 
432     EXPECT_EQ(nullptr, data);
433 
434     NativeStructPtr output_native;
435     mojo::internal::Deserialize<NativeStructPtr>(data, &output_native, nullptr);
436     EXPECT_TRUE(output_native.is_null());
437   }
438 
439   {
440     // Serialization of a native struct with null data.
441     NativeStructPtr native(NativeStruct::New());
442     size_t size =
443         mojo::internal::PrepareToSerialize<NativeStructPtr>(native, nullptr);
444     EXPECT_EQ(0u, size);
445     mojo::internal::FixedBufferForTesting buf(size);
446 
447     Data* data = nullptr;
448     mojo::internal::Serialize<NativeStructPtr>(std::move(native), &buf, &data,
449                                                nullptr);
450 
451     EXPECT_EQ(nullptr, data);
452 
453     NativeStructPtr output_native;
454     mojo::internal::Deserialize<NativeStructPtr>(data, &output_native, nullptr);
455     EXPECT_TRUE(output_native.is_null());
456   }
457 
458   {
459     NativeStructPtr native(NativeStruct::New());
460     native->data = Array<uint8_t>(2);
461     native->data[0] = 'X';
462     native->data[1] = 'Y';
463 
464     size_t size =
465         mojo::internal::PrepareToSerialize<NativeStructPtr>(native, nullptr);
466     EXPECT_EQ(16u, size);
467     mojo::internal::FixedBufferForTesting buf(size);
468 
469     Data* data = nullptr;
470     mojo::internal::Serialize<NativeStructPtr>(std::move(native), &buf, &data,
471                                                nullptr);
472 
473     EXPECT_NE(nullptr, data);
474 
475     NativeStructPtr output_native;
476     mojo::internal::Deserialize<NativeStructPtr>(data, &output_native, nullptr);
477     EXPECT_FALSE(output_native.is_null());
478     EXPECT_FALSE(output_native->data.is_null());
479     EXPECT_EQ(2u, output_native->data.size());
480     EXPECT_EQ('X', output_native->data[0]);
481     EXPECT_EQ('Y', output_native->data[1]);
482   }
483 }
484 
TEST_F(StructTest,Serialization_PublicAPI)485 TEST_F(StructTest, Serialization_PublicAPI) {
486   {
487     // A null struct pointer.
488     RectPtr null_struct;
489     mojo::Array<uint8_t> data = Rect::Serialize(&null_struct);
490     EXPECT_TRUE(data.empty());
491 
492     // Initialize it to non-null.
493     RectPtr output(Rect::New());
494     ASSERT_TRUE(Rect::Deserialize(std::move(data), &output));
495     EXPECT_TRUE(output.is_null());
496   }
497 
498   {
499     // A struct with no fields.
500     EmptyStructPtr empty_struct(EmptyStruct::New());
501     mojo::Array<uint8_t> data = EmptyStruct::Serialize(&empty_struct);
502     EXPECT_FALSE(data.empty());
503 
504     EmptyStructPtr output;
505     ASSERT_TRUE(EmptyStruct::Deserialize(std::move(data), &output));
506     EXPECT_FALSE(output.is_null());
507   }
508 
509   {
510     // A simple struct.
511     RectPtr rect = MakeRect();
512     RectPtr cloned_rect = rect.Clone();
513     mojo::Array<uint8_t> data = Rect::Serialize(&rect);
514 
515     RectPtr output;
516     ASSERT_TRUE(Rect::Deserialize(std::move(data), &output));
517     EXPECT_TRUE(output.Equals(cloned_rect));
518   }
519 
520   {
521     // A struct containing other objects.
522     NamedRegionPtr region(NamedRegion::New());
523     region->name.emplace("region");
524     region->rects.emplace(3);
525     for (size_t i = 0; i < region->rects->size(); ++i)
526       (*region->rects)[i] = MakeRect(static_cast<int32_t>(i) + 1);
527 
528     NamedRegionPtr cloned_region = region.Clone();
529     mojo::Array<uint8_t> data = NamedRegion::Serialize(&region);
530 
531     // Make sure that the serialized result gets pointers encoded properly.
532     mojo::Array<uint8_t> cloned_data = data.Clone();
533     NamedRegionPtr output;
534     ASSERT_TRUE(NamedRegion::Deserialize(std::move(cloned_data), &output));
535     EXPECT_TRUE(output.Equals(cloned_region));
536   }
537 
538   {
539     // Deserialization failure.
540     RectPtr rect = MakeRect();
541     mojo::Array<uint8_t> data = Rect::Serialize(&rect);
542 
543     NamedRegionPtr output;
544     EXPECT_FALSE(NamedRegion::Deserialize(std::move(data), &output));
545   }
546 }
547 
548 }  // namespace test
549 }  // namespace mojo
550