1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 //     * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 //     * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 #include <google/protobuf/util/internal/protostream_objectsource.h>
32 
33 #include <memory>
34 #ifndef _SHARED_PTR_H
35 #include <google/protobuf/stubs/shared_ptr.h>
36 #endif
37 #include <sstream>
38 
39 #include <google/protobuf/stubs/casts.h>
40 #include <google/protobuf/any.pb.h>
41 #include <google/protobuf/io/coded_stream.h>
42 #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
43 #include <google/protobuf/descriptor.h>
44 #include <google/protobuf/util/internal/expecting_objectwriter.h>
45 #include <google/protobuf/util/internal/testdata/books.pb.h>
46 #include <google/protobuf/util/internal/testdata/field_mask.pb.h>
47 #include <google/protobuf/util/internal/type_info_test_helper.h>
48 #include <google/protobuf/util/internal/constants.h>
49 #include <google/protobuf/stubs/strutil.h>
50 #include <google/protobuf/util/internal/testdata/anys.pb.h>
51 #include <google/protobuf/util/internal/testdata/maps.pb.h>
52 #include <google/protobuf/util/internal/testdata/struct.pb.h>
53 #include <google/protobuf/util/internal/testdata/timestamp_duration.pb.h>
54 #include <gtest/gtest.h>
55 
56 
57 namespace google {
58 namespace protobuf {
59 namespace util {
60 namespace converter {
61 
62 using google::protobuf::Descriptor;
63 using google::protobuf::DescriptorPool;
64 using google::protobuf::FileDescriptorProto;
65 using google::protobuf::Message;
66 using google::protobuf::io::ArrayInputStream;
67 using google::protobuf::io::CodedInputStream;
68 using util::Status;
69 using google::protobuf::testing::Author;
70 using google::protobuf::testing::BadAuthor;
71 using google::protobuf::testing::BadNestedBook;
72 using google::protobuf::testing::Book;
73 using google::protobuf::testing::Cyclic;
74 using google::protobuf::testing::Book_Label;
75 using google::protobuf::testing::NestedBook;
76 using google::protobuf::testing::PackedPrimitive;
77 using google::protobuf::testing::Primitive;
78 using google::protobuf::testing::more_author;
79 using google::protobuf::testing::maps::MapOut;
80 using google::protobuf::testing::maps::MapOutWireFormat;
81 using google::protobuf::testing::timestampduration::TimestampDuration;
82 using google::protobuf::testing::anys::AnyOut;
83 using google::protobuf::testing::anys::AnyM;
84 using google::protobuf::testing::FieldMaskTest;
85 using google::protobuf::testing::NestedFieldMask;
86 using google::protobuf::testing::structs::StructType;
87 using ::testing::_;
88 
89 
90 namespace {
GetTypeUrl(const Descriptor * descriptor)91 string GetTypeUrl(const Descriptor* descriptor) {
92   return string(kTypeServiceBaseUrl) + "/" + descriptor->full_name();
93 }
94 }  // namespace
95 
96 class ProtostreamObjectSourceTest
97     : public ::testing::TestWithParam<testing::TypeInfoSource> {
98  protected:
ProtostreamObjectSourceTest()99   ProtostreamObjectSourceTest()
100       : helper_(GetParam()),
101         mock_(),
102         ow_(&mock_),
103         use_lower_camel_for_enums_(false) {
104     helper_.ResetTypeInfo(Book::descriptor());
105   }
106 
~ProtostreamObjectSourceTest()107   virtual ~ProtostreamObjectSourceTest() {}
108 
DoTest(const Message & msg,const Descriptor * descriptor)109   void DoTest(const Message& msg, const Descriptor* descriptor) {
110     Status status = ExecuteTest(msg, descriptor);
111     EXPECT_EQ(Status::OK, status);
112   }
113 
ExecuteTest(const Message & msg,const Descriptor * descriptor)114   Status ExecuteTest(const Message& msg, const Descriptor* descriptor) {
115     ostringstream oss;
116     msg.SerializePartialToOstream(&oss);
117     string proto = oss.str();
118     ArrayInputStream arr_stream(proto.data(), proto.size());
119     CodedInputStream in_stream(&arr_stream);
120 
121     google::protobuf::scoped_ptr<ProtoStreamObjectSource> os(
122         helper_.NewProtoSource(&in_stream, GetTypeUrl(descriptor)));
123     if (use_lower_camel_for_enums_) os->set_use_lower_camel_for_enums(true);
124     os->set_max_recursion_depth(64);
125     return os->WriteTo(&mock_);
126   }
127 
PrepareExpectingObjectWriterForRepeatedPrimitive()128   void PrepareExpectingObjectWriterForRepeatedPrimitive() {
129     ow_.StartObject("")
130         ->StartList("repFix32")
131         ->RenderUint32("", bit_cast<uint32>(3201))
132         ->RenderUint32("", bit_cast<uint32>(0))
133         ->RenderUint32("", bit_cast<uint32>(3202))
134         ->EndList()
135         ->StartList("repU32")
136         ->RenderUint32("", bit_cast<uint32>(3203))
137         ->RenderUint32("", bit_cast<uint32>(0))
138         ->EndList()
139         ->StartList("repI32")
140         ->RenderInt32("", 0)
141         ->RenderInt32("", 3204)
142         ->RenderInt32("", 3205)
143         ->EndList()
144         ->StartList("repSf32")
145         ->RenderInt32("", 3206)
146         ->RenderInt32("", 0)
147         ->EndList()
148         ->StartList("repS32")
149         ->RenderInt32("", 0)
150         ->RenderInt32("", 3207)
151         ->RenderInt32("", 3208)
152         ->EndList()
153         ->StartList("repFix64")
154         ->RenderUint64("", bit_cast<uint64>(6401LL))
155         ->RenderUint64("", bit_cast<uint64>(0LL))
156         ->EndList()
157         ->StartList("repU64")
158         ->RenderUint64("", bit_cast<uint64>(0LL))
159         ->RenderUint64("", bit_cast<uint64>(6402LL))
160         ->RenderUint64("", bit_cast<uint64>(6403LL))
161         ->EndList()
162         ->StartList("repI64")
163         ->RenderInt64("", 6404L)
164         ->RenderInt64("", 0L)
165         ->EndList()
166         ->StartList("repSf64")
167         ->RenderInt64("", 0L)
168         ->RenderInt64("", 6405L)
169         ->RenderInt64("", 6406L)
170         ->EndList()
171         ->StartList("repS64")
172         ->RenderInt64("", 6407L)
173         ->RenderInt64("", 0L)
174         ->EndList()
175         ->StartList("repFloat")
176         ->RenderFloat("", 0.0f)
177         ->RenderFloat("", 32.1f)
178         ->RenderFloat("", 32.2f)
179         ->EndList()
180         ->StartList("repDouble")
181         ->RenderDouble("", 64.1L)
182         ->RenderDouble("", 0.0L)
183         ->EndList()
184         ->StartList("repBool")
185         ->RenderBool("", true)
186         ->RenderBool("", false)
187         ->EndList()
188         ->EndObject();
189   }
190 
PrepareRepeatedPrimitive()191   Primitive PrepareRepeatedPrimitive() {
192     Primitive primitive;
193     primitive.add_rep_fix32(3201);
194     primitive.add_rep_fix32(0);
195     primitive.add_rep_fix32(3202);
196     primitive.add_rep_u32(3203);
197     primitive.add_rep_u32(0);
198     primitive.add_rep_i32(0);
199     primitive.add_rep_i32(3204);
200     primitive.add_rep_i32(3205);
201     primitive.add_rep_sf32(3206);
202     primitive.add_rep_sf32(0);
203     primitive.add_rep_s32(0);
204     primitive.add_rep_s32(3207);
205     primitive.add_rep_s32(3208);
206     primitive.add_rep_fix64(6401L);
207     primitive.add_rep_fix64(0L);
208     primitive.add_rep_u64(0L);
209     primitive.add_rep_u64(6402L);
210     primitive.add_rep_u64(6403L);
211     primitive.add_rep_i64(6404L);
212     primitive.add_rep_i64(0L);
213     primitive.add_rep_sf64(0L);
214     primitive.add_rep_sf64(6405L);
215     primitive.add_rep_sf64(6406L);
216     primitive.add_rep_s64(6407L);
217     primitive.add_rep_s64(0L);
218     primitive.add_rep_float(0.0f);
219     primitive.add_rep_float(32.1f);
220     primitive.add_rep_float(32.2f);
221     primitive.add_rep_double(64.1L);
222     primitive.add_rep_double(0.0);
223     primitive.add_rep_bool(true);
224     primitive.add_rep_bool(false);
225 
226     PrepareExpectingObjectWriterForRepeatedPrimitive();
227     return primitive;
228   }
229 
PreparePackedPrimitive()230   PackedPrimitive PreparePackedPrimitive() {
231     PackedPrimitive primitive;
232     primitive.add_rep_fix32(3201);
233     primitive.add_rep_fix32(0);
234     primitive.add_rep_fix32(3202);
235     primitive.add_rep_u32(3203);
236     primitive.add_rep_u32(0);
237     primitive.add_rep_i32(0);
238     primitive.add_rep_i32(3204);
239     primitive.add_rep_i32(3205);
240     primitive.add_rep_sf32(3206);
241     primitive.add_rep_sf32(0);
242     primitive.add_rep_s32(0);
243     primitive.add_rep_s32(3207);
244     primitive.add_rep_s32(3208);
245     primitive.add_rep_fix64(6401L);
246     primitive.add_rep_fix64(0L);
247     primitive.add_rep_u64(0L);
248     primitive.add_rep_u64(6402L);
249     primitive.add_rep_u64(6403L);
250     primitive.add_rep_i64(6404L);
251     primitive.add_rep_i64(0L);
252     primitive.add_rep_sf64(0L);
253     primitive.add_rep_sf64(6405L);
254     primitive.add_rep_sf64(6406L);
255     primitive.add_rep_s64(6407L);
256     primitive.add_rep_s64(0L);
257     primitive.add_rep_float(0.0f);
258     primitive.add_rep_float(32.1f);
259     primitive.add_rep_float(32.2f);
260     primitive.add_rep_double(64.1L);
261     primitive.add_rep_double(0.0);
262     primitive.add_rep_bool(true);
263     primitive.add_rep_bool(false);
264 
265     PrepareExpectingObjectWriterForRepeatedPrimitive();
266     return primitive;
267   }
268 
UseLowerCamelForEnums()269   void UseLowerCamelForEnums() { use_lower_camel_for_enums_ = true; }
270 
271   testing::TypeInfoTestHelper helper_;
272 
273   ::testing::NiceMock<MockObjectWriter> mock_;
274   ExpectingObjectWriter ow_;
275   bool use_lower_camel_for_enums_;
276 };
277 
278 INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
279                         ProtostreamObjectSourceTest,
280                         ::testing::Values(
281                             testing::USE_TYPE_RESOLVER));
282 
TEST_P(ProtostreamObjectSourceTest,EmptyMessage)283 TEST_P(ProtostreamObjectSourceTest, EmptyMessage) {
284   Book empty;
285   ow_.StartObject("")->EndObject();
286   DoTest(empty, Book::descriptor());
287 }
288 
TEST_P(ProtostreamObjectSourceTest,Primitives)289 TEST_P(ProtostreamObjectSourceTest, Primitives) {
290   Primitive primitive;
291   primitive.set_fix32(3201);
292   primitive.set_u32(3202);
293   primitive.set_i32(3203);
294   primitive.set_sf32(3204);
295   primitive.set_s32(3205);
296   primitive.set_fix64(6401L);
297   primitive.set_u64(6402L);
298   primitive.set_i64(6403L);
299   primitive.set_sf64(6404L);
300   primitive.set_s64(6405L);
301   primitive.set_str("String Value");
302   primitive.set_bytes("Some Bytes");
303   primitive.set_float_(32.1f);
304   primitive.set_double_(64.1L);
305   primitive.set_bool_(true);
306 
307   ow_.StartObject("")
308       ->RenderUint32("fix32", bit_cast<uint32>(3201))
309       ->RenderUint32("u32", bit_cast<uint32>(3202))
310       ->RenderInt32("i32", 3203)
311       ->RenderInt32("sf32", 3204)
312       ->RenderInt32("s32", 3205)
313       ->RenderUint64("fix64", bit_cast<uint64>(6401LL))
314       ->RenderUint64("u64", bit_cast<uint64>(6402LL))
315       ->RenderInt64("i64", 6403L)
316       ->RenderInt64("sf64", 6404L)
317       ->RenderInt64("s64", 6405L)
318       ->RenderString("str", "String Value")
319       ->RenderBytes("bytes", "Some Bytes")
320       ->RenderFloat("float", 32.1f)
321       ->RenderDouble("double", 64.1L)
322       ->RenderBool("bool", true)
323       ->EndObject();
324   DoTest(primitive, Primitive::descriptor());
325 }
326 
TEST_P(ProtostreamObjectSourceTest,RepeatingPrimitives)327 TEST_P(ProtostreamObjectSourceTest, RepeatingPrimitives) {
328   Primitive primitive = PrepareRepeatedPrimitive();
329   primitive.add_rep_str("String One");
330   primitive.add_rep_str("String Two");
331   primitive.add_rep_bytes("Some Bytes");
332 
333   ow_.StartList("repStr")
334       ->RenderString("", "String One")
335       ->RenderString("", "String Two")
336       ->EndList()
337       ->StartList("repBytes")
338       ->RenderBytes("", "Some Bytes")
339       ->EndList();
340   DoTest(primitive, Primitive::descriptor());
341 }
342 
TEST_P(ProtostreamObjectSourceTest,CustomJsonName)343 TEST_P(ProtostreamObjectSourceTest, CustomJsonName) {
344   Author author;
345   author.set_id(12345);
346 
347   ow_.StartObject("")->RenderUint64("@id", 12345)->EndObject();
348   DoTest(author, Author::descriptor());
349 }
350 
TEST_P(ProtostreamObjectSourceTest,NestedMessage)351 TEST_P(ProtostreamObjectSourceTest, NestedMessage) {
352   Author* author = new Author();
353   author->set_name("Tolstoy");
354   Book book;
355   book.set_title("My Book");
356   book.set_allocated_author(author);
357 
358   ow_.StartObject("")
359       ->RenderString("title", "My Book")
360       ->StartObject("author")
361       ->RenderString("name", "Tolstoy")
362       ->EndObject()
363       ->EndObject();
364   DoTest(book, Book::descriptor());
365 }
366 
TEST_P(ProtostreamObjectSourceTest,RepeatingField)367 TEST_P(ProtostreamObjectSourceTest, RepeatingField) {
368   Author author;
369   author.set_alive(false);
370   author.set_name("john");
371   author.add_pseudonym("phil");
372   author.add_pseudonym("bob");
373 
374   ow_.StartObject("")
375       ->RenderBool("alive", false)
376       ->RenderString("name", "john")
377       ->StartList("pseudonym")
378       ->RenderString("", "phil")
379       ->RenderString("", "bob")
380       ->EndList()
381       ->EndObject();
382   DoTest(author, Author::descriptor());
383 }
384 
TEST_P(ProtostreamObjectSourceTest,PackedRepeatingFields)385 TEST_P(ProtostreamObjectSourceTest, PackedRepeatingFields) {
386   DoTest(PreparePackedPrimitive(), PackedPrimitive::descriptor());
387 }
388 
TEST_P(ProtostreamObjectSourceTest,NonPackedPackableFieldsActuallyPacked)389 TEST_P(ProtostreamObjectSourceTest, NonPackedPackableFieldsActuallyPacked) {
390   // Protostream is packed, but parse with non-packed Primitive.
391   DoTest(PreparePackedPrimitive(), Primitive::descriptor());
392 }
393 
TEST_P(ProtostreamObjectSourceTest,PackedPackableFieldNotActuallyPacked)394 TEST_P(ProtostreamObjectSourceTest, PackedPackableFieldNotActuallyPacked) {
395   // Protostream is not packed, but parse with PackedPrimitive.
396   DoTest(PrepareRepeatedPrimitive(), PackedPrimitive::descriptor());
397 }
398 
TEST_P(ProtostreamObjectSourceTest,BadAuthor)399 TEST_P(ProtostreamObjectSourceTest, BadAuthor) {
400   Author author;
401   author.set_alive(false);
402   author.set_name("john");
403   author.set_id(1234L);
404   author.add_pseudonym("phil");
405   author.add_pseudonym("bob");
406 
407   ow_.StartObject("")
408       ->StartList("alive")
409       ->RenderBool("", false)
410       ->EndList()
411       ->StartList("name")
412       ->RenderUint64("", static_cast<uint64>('j'))
413       ->RenderUint64("", static_cast<uint64>('o'))
414       ->RenderUint64("", static_cast<uint64>('h'))
415       ->RenderUint64("", static_cast<uint64>('n'))
416       ->EndList()
417       ->RenderString("pseudonym", "phil")
418       ->RenderString("pseudonym", "bob")
419       ->EndObject();
420   // Protostream created with Author, but parsed with BadAuthor.
421   DoTest(author, BadAuthor::descriptor());
422 }
423 
TEST_P(ProtostreamObjectSourceTest,NestedBookToBadNestedBook)424 TEST_P(ProtostreamObjectSourceTest, NestedBookToBadNestedBook) {
425   Book* book = new Book();
426   book->set_length(250);
427   book->set_published(2014L);
428   NestedBook nested;
429   nested.set_allocated_book(book);
430 
431   ow_.StartObject("")
432       ->StartList("book")
433       ->RenderUint32("", 24)  // tag for field length (3 << 3)
434       ->RenderUint32("", 250)
435       ->RenderUint32("", 32)  // tag for field published (4 << 3)
436       ->RenderUint32("", 2014)
437       ->EndList()
438       ->EndObject();
439   // Protostream created with NestedBook, but parsed with BadNestedBook.
440   DoTest(nested, BadNestedBook::descriptor());
441 }
442 
TEST_P(ProtostreamObjectSourceTest,BadNestedBookToNestedBook)443 TEST_P(ProtostreamObjectSourceTest, BadNestedBookToNestedBook) {
444   BadNestedBook nested;
445   nested.add_book(1);
446   nested.add_book(2);
447   nested.add_book(3);
448   nested.add_book(4);
449   nested.add_book(5);
450   nested.add_book(6);
451   nested.add_book(7);
452 
453   ow_.StartObject("")->StartObject("book")->EndObject()->EndObject();
454   // Protostream created with BadNestedBook, but parsed with NestedBook.
455   DoTest(nested, NestedBook::descriptor());
456 }
457 
TEST_P(ProtostreamObjectSourceTest,LongRepeatedListDoesNotBreakIntoMultipleJsonLists)458 TEST_P(ProtostreamObjectSourceTest,
459        LongRepeatedListDoesNotBreakIntoMultipleJsonLists) {
460   Book book;
461 
462   int repeat = 10000;
463   for (int i = 0; i < repeat; ++i) {
464     Book_Label* label = book.add_labels();
465     label->set_key(StrCat("i", i));
466     label->set_value(StrCat("v", i));
467   }
468 
469   // Make sure StartList and EndList are called exactly once (see b/18227499 for
470   // problems when this doesn't happen)
471   EXPECT_CALL(mock_, StartList(_)).Times(1);
472   EXPECT_CALL(mock_, EndList()).Times(1);
473 
474   DoTest(book, Book::descriptor());
475 }
476 
TEST_P(ProtostreamObjectSourceTest,LowerCamelEnumOutputTest)477 TEST_P(ProtostreamObjectSourceTest, LowerCamelEnumOutputTest) {
478   Book book;
479   book.set_type(Book::ACTION_AND_ADVENTURE);
480 
481   UseLowerCamelForEnums();
482 
483   ow_.StartObject("")->RenderString("type", "actionAndAdventure")->EndObject();
484   DoTest(book, Book::descriptor());
485 }
486 
TEST_P(ProtostreamObjectSourceTest,EnumCaseIsUnchangedByDefault)487 TEST_P(ProtostreamObjectSourceTest, EnumCaseIsUnchangedByDefault) {
488   Book book;
489   book.set_type(Book::ACTION_AND_ADVENTURE);
490   ow_.StartObject("")
491       ->RenderString("type", "ACTION_AND_ADVENTURE")
492       ->EndObject();
493   DoTest(book, Book::descriptor());
494 }
495 
TEST_P(ProtostreamObjectSourceTest,CyclicMessageDepthTest)496 TEST_P(ProtostreamObjectSourceTest, CyclicMessageDepthTest) {
497   Cyclic cyclic;
498   cyclic.set_m_int(123);
499 
500   Book* book = cyclic.mutable_m_book();
501   book->set_title("book title");
502   Cyclic* current = cyclic.mutable_m_cyclic();
503   Author* current_author = cyclic.add_m_author();
504   for (int i = 0; i < 63; ++i) {
505     Author* next = current_author->add_friend_();
506     next->set_id(i);
507     next->set_name(StrCat("author_name_", i));
508     next->set_alive(true);
509     current_author = next;
510   }
511 
512   // Recursive message with depth (65) > max (max is 64).
513   for (int i = 0; i < 64; ++i) {
514     Cyclic* next = current->mutable_m_cyclic();
515     next->set_m_str(StrCat("count_", i));
516     current = next;
517   }
518 
519   Status status = ExecuteTest(cyclic, Cyclic::descriptor());
520   EXPECT_EQ(util::error::INVALID_ARGUMENT, status.error_code());
521 }
522 
523 class ProtostreamObjectSourceMapsTest : public ProtostreamObjectSourceTest {
524  protected:
ProtostreamObjectSourceMapsTest()525   ProtostreamObjectSourceMapsTest() {
526     helper_.ResetTypeInfo(MapOut::descriptor());
527   }
528 };
529 
530 INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
531                         ProtostreamObjectSourceMapsTest,
532                         ::testing::Values(
533                             testing::USE_TYPE_RESOLVER));
534 
535 // Tests JSON map.
536 //
537 // This is the example expected output.
538 // {
539 //   "map1": {
540 //     "key1": {
541 //       "foo": "foovalue"
542 //     },
543 //     "key2": {
544 //       "foo": "barvalue"
545 //     }
546 //   },
547 //   "map2": {
548 //     "nestedself": {
549 //       "map1": {
550 //         "nested_key1": {
551 //           "foo": "nested_foo"
552 //         }
553 //       },
554 //       "bar": "nested_bar_string"
555 //     }
556 //   },
557 //   "map3": {
558 //     "111": "one one one"
559 //   },
560 //   "bar": "top bar"
561 // }
TEST_P(ProtostreamObjectSourceMapsTest,MapsTest)562 TEST_P(ProtostreamObjectSourceMapsTest, MapsTest) {
563   MapOut out;
564   (*out.mutable_map1())["key1"].set_foo("foovalue");
565   (*out.mutable_map1())["key2"].set_foo("barvalue");
566 
567   MapOut* nested_value = &(*out.mutable_map2())["nestedself"];
568   (*nested_value->mutable_map1())["nested_key1"].set_foo("nested_foo");
569   nested_value->set_bar("nested_bar_string");
570 
571   (*out.mutable_map3())[111] = "one one one";
572 
573   out.set_bar("top bar");
574 
575   ow_.StartObject("")
576       ->StartObject("map1")
577       ->StartObject("key1")
578       ->RenderString("foo", "foovalue")
579       ->EndObject()
580       ->StartObject("key2")
581       ->RenderString("foo", "barvalue")
582       ->EndObject()
583       ->StartObject("map2")
584       ->StartObject("nestedself")
585       ->StartObject("map1")
586       ->StartObject("nested_key1")
587       ->RenderString("foo", "nested_foo")
588       ->EndObject()
589       ->EndObject()
590       ->RenderString("bar", "nested_bar_string")
591       ->EndObject()
592       ->EndObject()
593       ->StartObject("map3")
594       ->RenderString("111", "one one one")
595       ->EndObject()
596       ->EndObject()
597       ->RenderString("bar", "top bar")
598       ->EndObject();
599 
600   DoTest(out, MapOut::descriptor());
601 }
602 
TEST_P(ProtostreamObjectSourceMapsTest,MissingKeysTest)603 TEST_P(ProtostreamObjectSourceMapsTest, MissingKeysTest) {
604   // MapOutWireFormat has the same wire representation with MapOut but uses
605   // repeated message fields to represent map fields so we can intentionally
606   // leave out the key field or the value field of a map entry.
607   MapOutWireFormat out;
608   // Create some map entries without keys. They will be rendered with the
609   // default values ("" for strings, "0" for integers, etc.).
610   // {
611   //   "map1": {
612   //     "": {
613   //       "foo": "foovalue"
614   //     }
615   //   },
616   //   "map2": {
617   //     "": {
618   //       "map1": {
619   //         "nested_key1": {
620   //           "foo": "nested_foo"
621   //         }
622   //       }
623   //     }
624   //   },
625   //   "map3": {
626   //     "0": "one one one"
627   //   },
628   //   "map4": {
629   //     "false": "bool"
630   //   }
631   // }
632   out.add_map1()->mutable_value()->set_foo("foovalue");
633   MapOut* nested = out.add_map2()->mutable_value();
634   (*nested->mutable_map1())["nested_key1"].set_foo("nested_foo");
635   out.add_map3()->set_value("one one one");
636   out.add_map4()->set_value("bool");
637 
638   ow_.StartObject("")
639       ->StartObject("map1")
640       ->StartObject("")
641       ->RenderString("foo", "foovalue")
642       ->EndObject()
643       ->EndObject()
644       ->StartObject("map2")
645       ->StartObject("")
646       ->StartObject("map1")
647       ->StartObject("nested_key1")
648       ->RenderString("foo", "nested_foo")
649       ->EndObject()
650       ->EndObject()
651       ->EndObject()
652       ->EndObject()
653       ->StartObject("map3")
654       ->RenderString("0", "one one one")
655       ->EndObject()
656       ->StartObject("map4")
657       ->RenderString("false", "bool")
658       ->EndObject()
659       ->EndObject();
660 
661   DoTest(out, MapOut::descriptor());
662 }
663 
664 class ProtostreamObjectSourceAnysTest : public ProtostreamObjectSourceTest {
665  protected:
ProtostreamObjectSourceAnysTest()666   ProtostreamObjectSourceAnysTest() {
667     helper_.ResetTypeInfo(AnyOut::descriptor(),
668                           google::protobuf::Any::descriptor());
669   }
670 };
671 
672 INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
673                         ProtostreamObjectSourceAnysTest,
674                         ::testing::Values(
675                             testing::USE_TYPE_RESOLVER));
676 
677 // Tests JSON any support.
678 //
679 // This is the example expected output.
680 // {
681 //   "any": {
682 //     "@type": "type.googleapis.com/google.protobuf.testing.anys.AnyM"
683 //     "foo": "foovalue"
684 //   }
685 // }
TEST_P(ProtostreamObjectSourceAnysTest,BasicAny)686 TEST_P(ProtostreamObjectSourceAnysTest, BasicAny) {
687   AnyOut out;
688   ::google::protobuf::Any* any = out.mutable_any();
689 
690   AnyM m;
691   m.set_foo("foovalue");
692   any->PackFrom(m);
693 
694   ow_.StartObject("")
695       ->StartObject("any")
696       ->RenderString("@type",
697                      "type.googleapis.com/google.protobuf.testing.anys.AnyM")
698       ->RenderString("foo", "foovalue")
699       ->EndObject()
700       ->EndObject();
701 
702   DoTest(out, AnyOut::descriptor());
703 }
704 
TEST_P(ProtostreamObjectSourceAnysTest,RecursiveAny)705 TEST_P(ProtostreamObjectSourceAnysTest, RecursiveAny) {
706   AnyOut out;
707   ::google::protobuf::Any* any = out.mutable_any();
708   any->set_type_url("type.googleapis.com/google.protobuf.Any");
709 
710   ::google::protobuf::Any nested_any;
711   nested_any.set_type_url(
712       "type.googleapis.com/google.protobuf.testing.anys.AnyM");
713 
714   AnyM m;
715   m.set_foo("foovalue");
716   nested_any.set_value(m.SerializeAsString());
717 
718   any->set_value(nested_any.SerializeAsString());
719 
720   ow_.StartObject("")
721       ->StartObject("any")
722       ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
723       ->StartObject("value")
724       ->RenderString("@type",
725                      "type.googleapis.com/google.protobuf.testing.anys.AnyM")
726       ->RenderString("foo", "foovalue")
727       ->EndObject()
728       ->EndObject()
729       ->EndObject();
730 
731   DoTest(out, AnyOut::descriptor());
732 }
733 
TEST_P(ProtostreamObjectSourceAnysTest,DoubleRecursiveAny)734 TEST_P(ProtostreamObjectSourceAnysTest, DoubleRecursiveAny) {
735   AnyOut out;
736   ::google::protobuf::Any* any = out.mutable_any();
737   any->set_type_url("type.googleapis.com/google.protobuf.Any");
738 
739   ::google::protobuf::Any nested_any;
740   nested_any.set_type_url("type.googleapis.com/google.protobuf.Any");
741 
742   ::google::protobuf::Any second_nested_any;
743   second_nested_any.set_type_url(
744       "type.googleapis.com/google.protobuf.testing.anys.AnyM");
745 
746   AnyM m;
747   m.set_foo("foovalue");
748   second_nested_any.set_value(m.SerializeAsString());
749   nested_any.set_value(second_nested_any.SerializeAsString());
750   any->set_value(nested_any.SerializeAsString());
751 
752   ow_.StartObject("")
753       ->StartObject("any")
754       ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
755       ->StartObject("value")
756       ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
757       ->StartObject("value")
758       ->RenderString("@type",
759                      "type.googleapis.com/google.protobuf.testing.anys.AnyM")
760       ->RenderString("foo", "foovalue")
761       ->EndObject()
762       ->EndObject()
763       ->EndObject()
764       ->EndObject();
765 
766   DoTest(out, AnyOut::descriptor());
767 }
768 
TEST_P(ProtostreamObjectSourceAnysTest,EmptyAnyOutputsEmptyObject)769 TEST_P(ProtostreamObjectSourceAnysTest, EmptyAnyOutputsEmptyObject) {
770   AnyOut out;
771   out.mutable_any();
772 
773   ow_.StartObject("")->StartObject("any")->EndObject()->EndObject();
774 
775   DoTest(out, AnyOut::descriptor());
776 }
777 
TEST_P(ProtostreamObjectSourceAnysTest,EmptyWithTypeAndNoValueOutputsType)778 TEST_P(ProtostreamObjectSourceAnysTest, EmptyWithTypeAndNoValueOutputsType) {
779   AnyOut out;
780   out.mutable_any()->set_type_url("foo.googleapis.com/my.Type");
781 
782   ow_.StartObject("")
783       ->StartObject("any")
784       ->RenderString("@type", "foo.googleapis.com/my.Type")
785       ->EndObject()
786       ->EndObject();
787 
788   DoTest(out, AnyOut::descriptor());
789 }
790 
TEST_P(ProtostreamObjectSourceAnysTest,MissingTypeUrlError)791 TEST_P(ProtostreamObjectSourceAnysTest, MissingTypeUrlError) {
792   AnyOut out;
793   ::google::protobuf::Any* any = out.mutable_any();
794 
795   AnyM m;
796   m.set_foo("foovalue");
797   any->set_value(m.SerializeAsString());
798 
799   // We start the "AnyOut" part and then fail when we hit the Any object.
800   ow_.StartObject("");
801 
802   Status status = ExecuteTest(out, AnyOut::descriptor());
803   EXPECT_EQ(util::error::INTERNAL, status.error_code());
804 }
805 
TEST_P(ProtostreamObjectSourceAnysTest,UnknownTypeServiceError)806 TEST_P(ProtostreamObjectSourceAnysTest, UnknownTypeServiceError) {
807   AnyOut out;
808   ::google::protobuf::Any* any = out.mutable_any();
809   any->set_type_url("foo.googleapis.com/my.own.Type");
810 
811   AnyM m;
812   m.set_foo("foovalue");
813   any->set_value(m.SerializeAsString());
814 
815   // We start the "AnyOut" part and then fail when we hit the Any object.
816   ow_.StartObject("");
817 
818   Status status = ExecuteTest(out, AnyOut::descriptor());
819   EXPECT_EQ(util::error::INTERNAL, status.error_code());
820 }
821 
TEST_P(ProtostreamObjectSourceAnysTest,UnknownTypeError)822 TEST_P(ProtostreamObjectSourceAnysTest, UnknownTypeError) {
823   AnyOut out;
824   ::google::protobuf::Any* any = out.mutable_any();
825   any->set_type_url("type.googleapis.com/unknown.Type");
826 
827   AnyM m;
828   m.set_foo("foovalue");
829   any->set_value(m.SerializeAsString());
830 
831   // We start the "AnyOut" part and then fail when we hit the Any object.
832   ow_.StartObject("");
833 
834   Status status = ExecuteTest(out, AnyOut::descriptor());
835   EXPECT_EQ(util::error::INTERNAL, status.error_code());
836 }
837 
838 class ProtostreamObjectSourceStructTest : public ProtostreamObjectSourceTest {
839  protected:
ProtostreamObjectSourceStructTest()840   ProtostreamObjectSourceStructTest() {
841     helper_.ResetTypeInfo(StructType::descriptor(),
842                           google::protobuf::Struct::descriptor());
843   }
844 };
845 
846 INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
847                         ProtostreamObjectSourceStructTest,
848                         ::testing::Values(
849                             testing::USE_TYPE_RESOLVER));
850 
851 // Tests struct
852 //
853 //  "object": {
854 //    "k1": 123,
855 //    "k2": true
856 //  }
TEST_P(ProtostreamObjectSourceStructTest,StructRenderSuccess)857 TEST_P(ProtostreamObjectSourceStructTest, StructRenderSuccess) {
858   StructType out;
859   google::protobuf::Struct* s = out.mutable_object();
860   s->mutable_fields()->operator[]("k1").set_number_value(123);
861   s->mutable_fields()->operator[]("k2").set_bool_value(true);
862 
863   ow_.StartObject("")
864       ->StartObject("object")
865       ->RenderDouble("k1", 123)
866       ->RenderBool("k2", true)
867       ->EndObject()
868       ->EndObject();
869 
870   DoTest(out, StructType::descriptor());
871 }
872 
TEST_P(ProtostreamObjectSourceStructTest,MissingValueSkipsField)873 TEST_P(ProtostreamObjectSourceStructTest, MissingValueSkipsField) {
874   StructType out;
875   google::protobuf::Struct* s = out.mutable_object();
876   s->mutable_fields()->operator[]("k1");
877 
878   ow_.StartObject("")->StartObject("object")->EndObject()->EndObject();
879 
880   DoTest(out, StructType::descriptor());
881 }
882 
883 class ProtostreamObjectSourceFieldMaskTest
884     : public ProtostreamObjectSourceTest {
885  protected:
ProtostreamObjectSourceFieldMaskTest()886   ProtostreamObjectSourceFieldMaskTest() {
887     helper_.ResetTypeInfo(FieldMaskTest::descriptor(),
888                           google::protobuf::FieldMask::descriptor());
889   }
890 };
891 
892 INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
893                         ProtostreamObjectSourceFieldMaskTest,
894                         ::testing::Values(
895                             testing::USE_TYPE_RESOLVER));
896 
TEST_P(ProtostreamObjectSourceFieldMaskTest,FieldMaskRenderSuccess)897 TEST_P(ProtostreamObjectSourceFieldMaskTest, FieldMaskRenderSuccess) {
898   FieldMaskTest out;
899   out.set_id("1");
900   out.mutable_single_mask()->add_paths("path1");
901   out.mutable_single_mask()->add_paths("snake_case_path2");
902   ::google::protobuf::FieldMask* mask = out.add_repeated_mask();
903   mask->add_paths("path3");
904   mask = out.add_repeated_mask();
905   mask->add_paths("snake_case_path4");
906   mask->add_paths("path5");
907   NestedFieldMask* nested = out.add_nested_mask();
908   nested->set_data("data");
909   nested->mutable_single_mask()->add_paths("nested.path1");
910   nested->mutable_single_mask()->add_paths("nested_field.snake_case_path2");
911   mask = nested->add_repeated_mask();
912   mask->add_paths("nested_field.path3");
913   mask->add_paths("nested.snake_case_path4");
914   mask = nested->add_repeated_mask();
915   mask->add_paths("nested.path5");
916   mask = nested->add_repeated_mask();
917   mask->add_paths(
918       "snake_case.map_field[\"map_key_should_be_ignored\"].nested_snake_case."
919       "map_field[\"map_key_sho\\\"uld_be_ignored\"]");
920 
921   ow_.StartObject("")
922       ->RenderString("id", "1")
923       ->RenderString("singleMask", "path1,snakeCasePath2")
924       ->StartList("repeatedMask")
925       ->RenderString("", "path3")
926       ->RenderString("", "snakeCasePath4,path5")
927       ->EndList()
928       ->StartList("nestedMask")
929       ->StartObject("")
930       ->RenderString("data", "data")
931       ->RenderString("singleMask", "nested.path1,nestedField.snakeCasePath2")
932       ->StartList("repeatedMask")
933       ->RenderString("", "nestedField.path3,nested.snakeCasePath4")
934       ->RenderString("", "nested.path5")
935       ->RenderString("",
936                      "snakeCase.mapField[\"map_key_should_be_ignored\"]."
937                      "nestedSnakeCase.mapField[\"map_key_sho\\\"uld_be_"
938                      "ignored\"]")
939       ->EndList()
940       ->EndObject()
941       ->EndList()
942       ->EndObject();
943 
944   DoTest(out, FieldMaskTest::descriptor());
945 }
946 
947 class ProtostreamObjectSourceTimestampTest
948     : public ProtostreamObjectSourceTest {
949  protected:
ProtostreamObjectSourceTimestampTest()950   ProtostreamObjectSourceTimestampTest() {
951     helper_.ResetTypeInfo(TimestampDuration::descriptor());
952   }
953 };
954 
955 INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
956                         ProtostreamObjectSourceTimestampTest,
957                         ::testing::Values(
958                             testing::USE_TYPE_RESOLVER));
959 
TEST_P(ProtostreamObjectSourceTimestampTest,InvalidTimestampBelowMinTest)960 TEST_P(ProtostreamObjectSourceTimestampTest, InvalidTimestampBelowMinTest) {
961   TimestampDuration out;
962   google::protobuf::Timestamp* ts = out.mutable_ts();
963   // Min allowed seconds - 1
964   ts->set_seconds(kTimestampMinSeconds - 1);
965   ow_.StartObject("");
966 
967   Status status = ExecuteTest(out, TimestampDuration::descriptor());
968   EXPECT_EQ(util::error::INTERNAL, status.error_code());
969 }
970 
TEST_P(ProtostreamObjectSourceTimestampTest,InvalidTimestampAboveMaxTest)971 TEST_P(ProtostreamObjectSourceTimestampTest, InvalidTimestampAboveMaxTest) {
972   TimestampDuration out;
973   google::protobuf::Timestamp* ts = out.mutable_ts();
974   // Max allowed seconds + 1
975   ts->set_seconds(kTimestampMaxSeconds + 1);
976   ow_.StartObject("");
977 
978   Status status = ExecuteTest(out, TimestampDuration::descriptor());
979   EXPECT_EQ(util::error::INTERNAL, status.error_code());
980 }
981 
TEST_P(ProtostreamObjectSourceTimestampTest,InvalidDurationBelowMinTest)982 TEST_P(ProtostreamObjectSourceTimestampTest, InvalidDurationBelowMinTest) {
983   TimestampDuration out;
984   google::protobuf::Duration* dur = out.mutable_dur();
985   // Min allowed seconds - 1
986   dur->set_seconds(kDurationMinSeconds - 1);
987   ow_.StartObject("");
988 
989   Status status = ExecuteTest(out, TimestampDuration::descriptor());
990   EXPECT_EQ(util::error::INTERNAL, status.error_code());
991 }
992 
TEST_P(ProtostreamObjectSourceTimestampTest,InvalidDurationAboveMaxTest)993 TEST_P(ProtostreamObjectSourceTimestampTest, InvalidDurationAboveMaxTest) {
994   TimestampDuration out;
995   google::protobuf::Duration* dur = out.mutable_dur();
996   // Min allowed seconds + 1
997   dur->set_seconds(kDurationMaxSeconds + 1);
998   ow_.StartObject("");
999 
1000   Status status = ExecuteTest(out, TimestampDuration::descriptor());
1001   EXPECT_EQ(util::error::INTERNAL, status.error_code());
1002 }
1003 
1004 }  // namespace converter
1005 }  // namespace util
1006 }  // namespace protobuf
1007 }  // namespace google
1008