• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <sstream>
35 
36 #include <google/protobuf/any.pb.h>
37 #include <google/protobuf/io/coded_stream.h>
38 #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
39 #include <google/protobuf/descriptor.h>
40 #include <google/protobuf/util/internal/expecting_objectwriter.h>
41 #include <google/protobuf/util/internal/testdata/anys.pb.h>
42 #include <google/protobuf/util/internal/testdata/books.pb.h>
43 #include <google/protobuf/util/internal/testdata/field_mask.pb.h>
44 #include <google/protobuf/util/internal/testdata/maps.pb.h>
45 #include <google/protobuf/util/internal/testdata/proto3.pb.h>
46 #include <google/protobuf/util/internal/testdata/struct.pb.h>
47 #include <google/protobuf/util/internal/testdata/timestamp_duration.pb.h>
48 #include <google/protobuf/util/internal/type_info_test_helper.h>
49 #include <google/protobuf/util/internal/constants.h>
50 #include <gtest/gtest.h>
51 #include <google/protobuf/stubs/casts.h>
52 
53 
54 namespace google {
55 namespace protobuf {
56 namespace util {
57 namespace converter {
58 
59 using ::google::protobuf::Any;
60 using io::ArrayInputStream;
61 using io::CodedInputStream;
62 using proto_util_converter::testing::AnyM;
63 using proto_util_converter::testing::AnyOut;
64 using proto_util_converter::testing::Author;
65 using proto_util_converter::testing::BadAuthor;
66 using proto_util_converter::testing::BadNestedBook;
67 using proto_util_converter::testing::Book;
68 using proto_util_converter::testing::Book_Label;
69 using proto_util_converter::testing::Cyclic;
70 using proto_util_converter::testing::FieldMaskTest;
71 using proto_util_converter::testing::MapOut;
72 using proto_util_converter::testing::MapOutWireFormat;
73 using proto_util_converter::testing::NestedBook;
74 using proto_util_converter::testing::NestedFieldMask;
75 using proto_util_converter::testing::PackedPrimitive;
76 using proto_util_converter::testing::Primitive;
77 using proto_util_converter::testing::Proto3Message;
78 using proto_util_converter::testing::StructType;
79 using proto_util_converter::testing::TimestampDuration;
80 using ::testing::_;
81 using util::Status;
82 
83 
84 namespace {
GetTypeUrl(const Descriptor * descriptor)85 std::string GetTypeUrl(const Descriptor* descriptor) {
86   return std::string(kTypeServiceBaseUrl) + "/" + descriptor->full_name();
87 }
88 }  // namespace
89 
90 class ProtostreamObjectSourceTest
91     : public ::testing::TestWithParam<testing::TypeInfoSource> {
92  protected:
ProtostreamObjectSourceTest()93   ProtostreamObjectSourceTest()
94       : helper_(GetParam()),
95         mock_(),
96         ow_(&mock_),
97         use_lower_camel_for_enums_(false),
98         use_ints_for_enums_(false),
99         use_preserve_proto_field_names_(false),
100         add_trailing_zeros_(false),
101         render_unknown_enum_values_(true) {
102     helper_.ResetTypeInfo(Book::descriptor(), Proto3Message::descriptor());
103   }
104 
~ProtostreamObjectSourceTest()105   virtual ~ProtostreamObjectSourceTest() {}
106 
DoTest(const Message & msg,const Descriptor * descriptor)107   void DoTest(const Message& msg, const Descriptor* descriptor) {
108     Status status = ExecuteTest(msg, descriptor);
109     EXPECT_EQ(util::Status(), status);
110   }
111 
ExecuteTest(const Message & msg,const Descriptor * descriptor)112   Status ExecuteTest(const Message& msg, const Descriptor* descriptor) {
113     std::ostringstream oss;
114     msg.SerializePartialToOstream(&oss);
115     std::string proto = oss.str();
116     ArrayInputStream arr_stream(proto.data(), proto.size());
117     CodedInputStream in_stream(&arr_stream);
118 
119     std::unique_ptr<ProtoStreamObjectSource> os(
120         helper_.NewProtoSource(&in_stream, GetTypeUrl(descriptor)));
121     if (use_lower_camel_for_enums_) os->set_use_lower_camel_for_enums(true);
122     if (use_ints_for_enums_) os->set_use_ints_for_enums(true);
123     if (use_preserve_proto_field_names_)
124       os->set_preserve_proto_field_names(true);
125     os->set_max_recursion_depth(64);
126     return os->WriteTo(&mock_);
127   }
128 
PrepareExpectingObjectWriterForRepeatedPrimitive()129   void PrepareExpectingObjectWriterForRepeatedPrimitive() {
130     ow_.StartObject("")
131         ->StartList("repFix32")
132         ->RenderUint32("", bit_cast<uint32>(3201))
133         ->RenderUint32("", bit_cast<uint32>(0))
134         ->RenderUint32("", bit_cast<uint32>(3202))
135         ->EndList()
136         ->StartList("repU32")
137         ->RenderUint32("", bit_cast<uint32>(3203))
138         ->RenderUint32("", bit_cast<uint32>(0))
139         ->EndList()
140         ->StartList("repI32")
141         ->RenderInt32("", 0)
142         ->RenderInt32("", 3204)
143         ->RenderInt32("", 3205)
144         ->EndList()
145         ->StartList("repSf32")
146         ->RenderInt32("", 3206)
147         ->RenderInt32("", 0)
148         ->EndList()
149         ->StartList("repS32")
150         ->RenderInt32("", 0)
151         ->RenderInt32("", 3207)
152         ->RenderInt32("", 3208)
153         ->EndList()
154         ->StartList("repFix64")
155         ->RenderUint64("", bit_cast<uint64>(int64{6401}))
156         ->RenderUint64("", bit_cast<uint64>(int64{0}))
157         ->EndList()
158         ->StartList("repU64")
159         ->RenderUint64("", bit_cast<uint64>(int64{0}))
160         ->RenderUint64("", bit_cast<uint64>(int64{6402}))
161         ->RenderUint64("", bit_cast<uint64>(int64{6403}))
162         ->EndList()
163         ->StartList("repI64")
164         ->RenderInt64("", 6404L)
165         ->RenderInt64("", 0L)
166         ->EndList()
167         ->StartList("repSf64")
168         ->RenderInt64("", 0L)
169         ->RenderInt64("", 6405L)
170         ->RenderInt64("", 6406L)
171         ->EndList()
172         ->StartList("repS64")
173         ->RenderInt64("", 6407L)
174         ->RenderInt64("", 0L)
175         ->EndList()
176         ->StartList("repFloat")
177         ->RenderFloat("", 0.0f)
178         ->RenderFloat("", 32.1f)
179         ->RenderFloat("", 32.2f)
180         ->EndList()
181         ->StartList("repDouble")
182         ->RenderDouble("", 64.1L)
183         ->RenderDouble("", 0.0L)
184         ->EndList()
185         ->StartList("repBool")
186         ->RenderBool("", true)
187         ->RenderBool("", false)
188         ->EndList()
189         ->EndObject();
190   }
191 
PrepareRepeatedPrimitive()192   Primitive PrepareRepeatedPrimitive() {
193     Primitive primitive;
194     primitive.add_rep_fix32(3201);
195     primitive.add_rep_fix32(0);
196     primitive.add_rep_fix32(3202);
197     primitive.add_rep_u32(3203);
198     primitive.add_rep_u32(0);
199     primitive.add_rep_i32(0);
200     primitive.add_rep_i32(3204);
201     primitive.add_rep_i32(3205);
202     primitive.add_rep_sf32(3206);
203     primitive.add_rep_sf32(0);
204     primitive.add_rep_s32(0);
205     primitive.add_rep_s32(3207);
206     primitive.add_rep_s32(3208);
207     primitive.add_rep_fix64(6401L);
208     primitive.add_rep_fix64(0L);
209     primitive.add_rep_u64(0L);
210     primitive.add_rep_u64(6402L);
211     primitive.add_rep_u64(6403L);
212     primitive.add_rep_i64(6404L);
213     primitive.add_rep_i64(0L);
214     primitive.add_rep_sf64(0L);
215     primitive.add_rep_sf64(6405L);
216     primitive.add_rep_sf64(6406L);
217     primitive.add_rep_s64(6407L);
218     primitive.add_rep_s64(0L);
219     primitive.add_rep_float(0.0f);
220     primitive.add_rep_float(32.1f);
221     primitive.add_rep_float(32.2f);
222     primitive.add_rep_double(64.1L);
223     primitive.add_rep_double(0.0);
224     primitive.add_rep_bool(true);
225     primitive.add_rep_bool(false);
226 
227     PrepareExpectingObjectWriterForRepeatedPrimitive();
228     return primitive;
229   }
230 
PreparePackedPrimitive()231   PackedPrimitive PreparePackedPrimitive() {
232     PackedPrimitive primitive;
233     primitive.add_rep_fix32(3201);
234     primitive.add_rep_fix32(0);
235     primitive.add_rep_fix32(3202);
236     primitive.add_rep_u32(3203);
237     primitive.add_rep_u32(0);
238     primitive.add_rep_i32(0);
239     primitive.add_rep_i32(3204);
240     primitive.add_rep_i32(3205);
241     primitive.add_rep_sf32(3206);
242     primitive.add_rep_sf32(0);
243     primitive.add_rep_s32(0);
244     primitive.add_rep_s32(3207);
245     primitive.add_rep_s32(3208);
246     primitive.add_rep_fix64(6401L);
247     primitive.add_rep_fix64(0L);
248     primitive.add_rep_u64(0L);
249     primitive.add_rep_u64(6402L);
250     primitive.add_rep_u64(6403L);
251     primitive.add_rep_i64(6404L);
252     primitive.add_rep_i64(0L);
253     primitive.add_rep_sf64(0L);
254     primitive.add_rep_sf64(6405L);
255     primitive.add_rep_sf64(6406L);
256     primitive.add_rep_s64(6407L);
257     primitive.add_rep_s64(0L);
258     primitive.add_rep_float(0.0f);
259     primitive.add_rep_float(32.1f);
260     primitive.add_rep_float(32.2f);
261     primitive.add_rep_double(64.1L);
262     primitive.add_rep_double(0.0);
263     primitive.add_rep_bool(true);
264     primitive.add_rep_bool(false);
265 
266     PrepareExpectingObjectWriterForRepeatedPrimitive();
267     return primitive;
268   }
269 
UseLowerCamelForEnums()270   void UseLowerCamelForEnums() { use_lower_camel_for_enums_ = true; }
271 
UseIntsForEnums()272   void UseIntsForEnums() { use_ints_for_enums_ = true; }
273 
UsePreserveProtoFieldNames()274   void UsePreserveProtoFieldNames() { use_preserve_proto_field_names_ = true; }
275 
AddTrailingZeros()276   void AddTrailingZeros() { add_trailing_zeros_ = true; }
277 
SetRenderUnknownEnumValues(bool value)278   void SetRenderUnknownEnumValues(bool value) {
279     render_unknown_enum_values_ = value;
280   }
281 
282   testing::TypeInfoTestHelper helper_;
283 
284   ::testing::NiceMock<MockObjectWriter> mock_;
285   ExpectingObjectWriter ow_;
286   bool use_lower_camel_for_enums_;
287   bool use_ints_for_enums_;
288   bool use_preserve_proto_field_names_;
289   bool add_trailing_zeros_;
290   bool render_unknown_enum_values_;
291 };
292 
293 INSTANTIATE_TEST_SUITE_P(DifferentTypeInfoSourceTest,
294                          ProtostreamObjectSourceTest,
295                          ::testing::Values(
296                              testing::USE_TYPE_RESOLVER));
297 
TEST_P(ProtostreamObjectSourceTest,EmptyMessage)298 TEST_P(ProtostreamObjectSourceTest, EmptyMessage) {
299   Book empty;
300   ow_.StartObject("")->EndObject();
301   DoTest(empty, Book::descriptor());
302 }
303 
TEST_P(ProtostreamObjectSourceTest,Primitives)304 TEST_P(ProtostreamObjectSourceTest, Primitives) {
305   Primitive primitive;
306   primitive.set_fix32(3201);
307   primitive.set_u32(3202);
308   primitive.set_i32(3203);
309   primitive.set_sf32(3204);
310   primitive.set_s32(3205);
311   primitive.set_fix64(6401L);
312   primitive.set_u64(6402L);
313   primitive.set_i64(6403L);
314   primitive.set_sf64(6404L);
315   primitive.set_s64(6405L);
316   primitive.set_str("String Value");
317   primitive.set_bytes("Some Bytes");
318   primitive.set_float_(32.1f);
319   primitive.set_double_(64.1L);
320   primitive.set_bool_(true);
321 
322   ow_.StartObject("")
323       ->RenderUint32("fix32", bit_cast<uint32>(3201))
324       ->RenderUint32("u32", bit_cast<uint32>(3202))
325       ->RenderInt32("i32", 3203)
326       ->RenderInt32("sf32", 3204)
327       ->RenderInt32("s32", 3205)
328       ->RenderUint64("fix64", bit_cast<uint64>(int64{6401}))
329       ->RenderUint64("u64", bit_cast<uint64>(int64{6402}))
330       ->RenderInt64("i64", 6403L)
331       ->RenderInt64("sf64", 6404L)
332       ->RenderInt64("s64", 6405L)
333       ->RenderString("str", "String Value")
334       ->RenderBytes("bytes", "Some Bytes")
335       ->RenderFloat("float", 32.1f)
336       ->RenderDouble("double", 64.1L)
337       ->RenderBool("bool", true)
338       ->EndObject();
339   DoTest(primitive, Primitive::descriptor());
340 }
341 
TEST_P(ProtostreamObjectSourceTest,RepeatingPrimitives)342 TEST_P(ProtostreamObjectSourceTest, RepeatingPrimitives) {
343   Primitive primitive = PrepareRepeatedPrimitive();
344   primitive.add_rep_str("String One");
345   primitive.add_rep_str("String Two");
346   primitive.add_rep_bytes("Some Bytes");
347 
348   ow_.StartList("repStr")
349       ->RenderString("", "String One")
350       ->RenderString("", "String Two")
351       ->EndList()
352       ->StartList("repBytes")
353       ->RenderBytes("", "Some Bytes")
354       ->EndList();
355   DoTest(primitive, Primitive::descriptor());
356 }
357 
TEST_P(ProtostreamObjectSourceTest,CustomJsonName)358 TEST_P(ProtostreamObjectSourceTest, CustomJsonName) {
359   Author author;
360   author.set_id(12345);
361 
362   ow_.StartObject("")->RenderUint64("@id", 12345)->EndObject();
363   DoTest(author, Author::descriptor());
364 }
365 
TEST_P(ProtostreamObjectSourceTest,NestedMessage)366 TEST_P(ProtostreamObjectSourceTest, NestedMessage) {
367   Author* author = new Author();
368   author->set_name("Tolstoy");
369   Book book;
370   book.set_title("My Book");
371   book.set_allocated_author(author);
372 
373   ow_.StartObject("")
374       ->RenderString("title", "My Book")
375       ->StartObject("author")
376       ->RenderString("name", "Tolstoy")
377       ->EndObject()
378       ->EndObject();
379   DoTest(book, Book::descriptor());
380 }
381 
TEST_P(ProtostreamObjectSourceTest,RepeatingField)382 TEST_P(ProtostreamObjectSourceTest, RepeatingField) {
383   Author author;
384   author.set_alive(false);
385   author.set_name("john");
386   author.add_pseudonym("phil");
387   author.add_pseudonym("bob");
388 
389   ow_.StartObject("")
390       ->RenderBool("alive", false)
391       ->RenderString("name", "john")
392       ->StartList("pseudonym")
393       ->RenderString("", "phil")
394       ->RenderString("", "bob")
395       ->EndList()
396       ->EndObject();
397   DoTest(author, Author::descriptor());
398 }
399 
TEST_P(ProtostreamObjectSourceTest,PackedRepeatingFields)400 TEST_P(ProtostreamObjectSourceTest, PackedRepeatingFields) {
401   DoTest(PreparePackedPrimitive(), PackedPrimitive::descriptor());
402 }
403 
TEST_P(ProtostreamObjectSourceTest,NonPackedPackableFieldsActuallyPacked)404 TEST_P(ProtostreamObjectSourceTest, NonPackedPackableFieldsActuallyPacked) {
405   // Protostream is packed, but parse with non-packed Primitive.
406   DoTest(PreparePackedPrimitive(), Primitive::descriptor());
407 }
408 
TEST_P(ProtostreamObjectSourceTest,PackedPackableFieldNotActuallyPacked)409 TEST_P(ProtostreamObjectSourceTest, PackedPackableFieldNotActuallyPacked) {
410   // Protostream is not packed, but parse with PackedPrimitive.
411   DoTest(PrepareRepeatedPrimitive(), PackedPrimitive::descriptor());
412 }
413 
TEST_P(ProtostreamObjectSourceTest,BadAuthor)414 TEST_P(ProtostreamObjectSourceTest, BadAuthor) {
415   Author author;
416   author.set_alive(false);
417   author.set_name("john");
418   author.set_id(1234L);
419   author.add_pseudonym("phil");
420   author.add_pseudonym("bob");
421 
422   ow_.StartObject("")
423       ->StartList("alive")
424       ->RenderBool("", false)
425       ->EndList()
426       ->StartList("name")
427       ->RenderUint64("", static_cast<uint64>('j'))
428       ->RenderUint64("", static_cast<uint64>('o'))
429       ->RenderUint64("", static_cast<uint64>('h'))
430       ->RenderUint64("", static_cast<uint64>('n'))
431       ->EndList()
432       ->RenderString("pseudonym", "phil")
433       ->RenderString("pseudonym", "bob")
434       ->EndObject();
435   // Protostream created with Author, but parsed with BadAuthor.
436   DoTest(author, BadAuthor::descriptor());
437 }
438 
TEST_P(ProtostreamObjectSourceTest,NestedBookToBadNestedBook)439 TEST_P(ProtostreamObjectSourceTest, NestedBookToBadNestedBook) {
440   Book* book = new Book();
441   book->set_length(250);
442   book->set_published(2014L);
443   NestedBook nested;
444   nested.set_allocated_book(book);
445 
446   ow_.StartObject("")
447       ->StartList("book")
448       ->RenderUint32("", 24)  // tag for field length (3 << 3)
449       ->RenderUint32("", 250)
450       ->RenderUint32("", 32)  // tag for field published (4 << 3)
451       ->RenderUint32("", 2014)
452       ->EndList()
453       ->EndObject();
454   // Protostream created with NestedBook, but parsed with BadNestedBook.
455   DoTest(nested, BadNestedBook::descriptor());
456 }
457 
TEST_P(ProtostreamObjectSourceTest,BadNestedBookToNestedBook)458 TEST_P(ProtostreamObjectSourceTest, BadNestedBookToNestedBook) {
459   BadNestedBook nested;
460   nested.add_book(1);
461   nested.add_book(2);
462   nested.add_book(3);
463   nested.add_book(4);
464   nested.add_book(5);
465   nested.add_book(6);
466   nested.add_book(7);
467 
468   ow_.StartObject("")->StartObject("book")->EndObject()->EndObject();
469   // Protostream created with BadNestedBook, but parsed with NestedBook.
470   DoTest(nested, NestedBook::descriptor());
471 }
472 
TEST_P(ProtostreamObjectSourceTest,LongRepeatedListDoesNotBreakIntoMultipleJsonLists)473 TEST_P(ProtostreamObjectSourceTest,
474        LongRepeatedListDoesNotBreakIntoMultipleJsonLists) {
475   Book book;
476 
477   int repeat = 10000;
478   for (int i = 0; i < repeat; ++i) {
479     Book_Label* label = book.add_labels();
480     label->set_key(StrCat("i", i));
481     label->set_value(StrCat("v", i));
482   }
483 
484   // Make sure StartList and EndList are called exactly once (see b/18227499 for
485   // problems when this doesn't happen)
486   EXPECT_CALL(mock_, StartList(_)).Times(1);
487   EXPECT_CALL(mock_, EndList()).Times(1);
488 
489   DoTest(book, Book::descriptor());
490 }
491 
TEST_P(ProtostreamObjectSourceTest,LowerCamelEnumOutputMacroCase)492 TEST_P(ProtostreamObjectSourceTest, LowerCamelEnumOutputMacroCase) {
493   Book book;
494   book.set_type(Book::ACTION_AND_ADVENTURE);
495 
496   UseLowerCamelForEnums();
497 
498   ow_.StartObject("")->RenderString("type", "actionAndAdventure")->EndObject();
499   DoTest(book, Book::descriptor());
500 }
501 
TEST_P(ProtostreamObjectSourceTest,LowerCamelEnumOutputSnakeCase)502 TEST_P(ProtostreamObjectSourceTest, LowerCamelEnumOutputSnakeCase) {
503   Book book;
504   book.set_type(Book::arts_and_photography);
505 
506   UseLowerCamelForEnums();
507 
508   ow_.StartObject("")->RenderString("type", "artsAndPhotography")->EndObject();
509   DoTest(book, Book::descriptor());
510 }
511 
TEST_P(ProtostreamObjectSourceTest,LowerCamelEnumOutputWithNumber)512 TEST_P(ProtostreamObjectSourceTest, LowerCamelEnumOutputWithNumber) {
513   Book book;
514   book.set_type(Book::I18N_Tech);
515 
516   UseLowerCamelForEnums();
517 
518   ow_.StartObject("")->RenderString("type", "i18nTech")->EndObject();
519   DoTest(book, Book::descriptor());
520 }
521 
TEST_P(ProtostreamObjectSourceTest,EnumCaseIsUnchangedByDefault)522 TEST_P(ProtostreamObjectSourceTest, EnumCaseIsUnchangedByDefault) {
523   Book book;
524   book.set_type(Book::ACTION_AND_ADVENTURE);
525   ow_.StartObject("")
526       ->RenderString("type", "ACTION_AND_ADVENTURE")
527       ->EndObject();
528   DoTest(book, Book::descriptor());
529 }
530 
TEST_P(ProtostreamObjectSourceTest,UseIntsForEnumsTest)531 TEST_P(ProtostreamObjectSourceTest, UseIntsForEnumsTest) {
532   Book book;
533   book.set_type(Book::ACTION_AND_ADVENTURE);
534 
535   UseIntsForEnums();
536 
537   ow_.StartObject("")->RenderInt32("type", 3)->EndObject();
538   DoTest(book, Book::descriptor());
539 }
540 
TEST_P(ProtostreamObjectSourceTest,UsePreserveProtoFieldNames)541 TEST_P(ProtostreamObjectSourceTest, UsePreserveProtoFieldNames) {
542   Book book;
543   book.set_snake_field("foo");
544 
545   UsePreserveProtoFieldNames();
546 
547   ow_.StartObject("")->RenderString("snake_field", "foo")->EndObject();
548   DoTest(book, Book::descriptor());
549 }
550 
TEST_P(ProtostreamObjectSourceTest,UnknownEnumAreDroppedWhenRenderUnknownEnumValuesIsUnset)551 TEST_P(ProtostreamObjectSourceTest,
552        UnknownEnumAreDroppedWhenRenderUnknownEnumValuesIsUnset) {
553   Proto3Message message;
554   message.set_enum_value(static_cast<Proto3Message::NestedEnum>(1234));
555 
556   SetRenderUnknownEnumValues(false);
557 
558   // Unknown enum values are not output.
559   ow_.StartObject("")->EndObject();
560   DoTest(message, Proto3Message::descriptor());
561 }
562 
TEST_P(ProtostreamObjectSourceTest,UnknownEnumAreOutputWhenRenderUnknownEnumValuesIsSet)563 TEST_P(ProtostreamObjectSourceTest,
564        UnknownEnumAreOutputWhenRenderUnknownEnumValuesIsSet) {
565   Proto3Message message;
566   message.set_enum_value(static_cast<Proto3Message::NestedEnum>(1234));
567 
568   SetRenderUnknownEnumValues(true);
569 
570   // Unknown enum values are output.
571   ow_.StartObject("")->RenderInt32("enumValue", 1234)->EndObject();
572   DoTest(message, Proto3Message::descriptor());
573 }
574 
TEST_P(ProtostreamObjectSourceTest,CyclicMessageDepthTest)575 TEST_P(ProtostreamObjectSourceTest, CyclicMessageDepthTest) {
576   Cyclic cyclic;
577   cyclic.set_m_int(123);
578 
579   Book* book = cyclic.mutable_m_book();
580   book->set_title("book title");
581   Cyclic* current = cyclic.mutable_m_cyclic();
582   Author* current_author = cyclic.add_m_author();
583   for (int i = 0; i < 63; ++i) {
584     Author* next = current_author->add_friend_();
585     next->set_id(i);
586     next->set_name(StrCat("author_name_", i));
587     next->set_alive(true);
588     current_author = next;
589   }
590 
591   // Recursive message with depth (65) > max (max is 64).
592   for (int i = 0; i < 64; ++i) {
593     Cyclic* next = current->mutable_m_cyclic();
594     next->set_m_str(StrCat("count_", i));
595     current = next;
596   }
597 
598   Status status = ExecuteTest(cyclic, Cyclic::descriptor());
599   EXPECT_EQ(util::error::INVALID_ARGUMENT, status.code());
600 }
601 
602 class ProtostreamObjectSourceMapsTest : public ProtostreamObjectSourceTest {
603  protected:
ProtostreamObjectSourceMapsTest()604   ProtostreamObjectSourceMapsTest() {
605     helper_.ResetTypeInfo(MapOut::descriptor());
606   }
607 };
608 
609 INSTANTIATE_TEST_SUITE_P(DifferentTypeInfoSourceTest,
610                          ProtostreamObjectSourceMapsTest,
611                          ::testing::Values(
612                              testing::USE_TYPE_RESOLVER));
613 
614 // Tests JSON map.
615 //
616 // This is the example expected output.
617 // {
618 //   "map1": {
619 //     "key1": {
620 //       "foo": "foovalue"
621 //     },
622 //     "key2": {
623 //       "foo": "barvalue"
624 //     }
625 //   },
626 //   "map2": {
627 //     "nestedself": {
628 //       "map1": {
629 //         "nested_key1": {
630 //           "foo": "nested_foo"
631 //         }
632 //       },
633 //       "bar": "nested_bar_string"
634 //     }
635 //   },
636 //   "map3": {
637 //     "111": "one one one"
638 //   },
639 //   "bar": "top bar"
640 // }
TEST_P(ProtostreamObjectSourceMapsTest,MapsTest)641 TEST_P(ProtostreamObjectSourceMapsTest, MapsTest) {
642   MapOut out;
643   (*out.mutable_map1())["key1"].set_foo("foovalue");
644   (*out.mutable_map1())["key2"].set_foo("barvalue");
645 
646   MapOut* nested_value = &(*out.mutable_map2())["nestedself"];
647   (*nested_value->mutable_map1())["nested_key1"].set_foo("nested_foo");
648   nested_value->set_bar("nested_bar_string");
649 
650   (*out.mutable_map3())[111] = "one one one";
651 
652   out.set_bar("top bar");
653 
654   ow_.StartObject("")
655       ->StartObject("map1")
656       ->StartObject("key1")
657       ->RenderString("foo", "foovalue")
658       ->EndObject()
659       ->StartObject("key2")
660       ->RenderString("foo", "barvalue")
661       ->EndObject()
662       ->StartObject("map2")
663       ->StartObject("nestedself")
664       ->StartObject("map1")
665       ->StartObject("nested_key1")
666       ->RenderString("foo", "nested_foo")
667       ->EndObject()
668       ->EndObject()
669       ->RenderString("bar", "nested_bar_string")
670       ->EndObject()
671       ->EndObject()
672       ->StartObject("map3")
673       ->RenderString("111", "one one one")
674       ->EndObject()
675       ->EndObject()
676       ->RenderString("bar", "top bar")
677       ->EndObject();
678 
679   DoTest(out, MapOut::descriptor());
680 }
681 
TEST_P(ProtostreamObjectSourceMapsTest,MissingKeysTest)682 TEST_P(ProtostreamObjectSourceMapsTest, MissingKeysTest) {
683   // MapOutWireFormat has the same wire representation with MapOut but uses
684   // repeated message fields to represent map fields so we can intentionally
685   // leave out the key field or the value field of a map entry.
686   MapOutWireFormat out;
687   // Create some map entries without keys. They will be rendered with the
688   // default values ("" for strings, "0" for integers, etc.).
689   // {
690   //   "map1": {
691   //     "": {
692   //       "foo": "foovalue"
693   //     }
694   //   },
695   //   "map2": {
696   //     "": {
697   //       "map1": {
698   //         "nested_key1": {
699   //           "foo": "nested_foo"
700   //         }
701   //       }
702   //     }
703   //   },
704   //   "map3": {
705   //     "0": "one one one"
706   //   },
707   //   "map4": {
708   //     "false": "bool"
709   //   }
710   // }
711   out.add_map1()->mutable_value()->set_foo("foovalue");
712   MapOut* nested = out.add_map2()->mutable_value();
713   (*nested->mutable_map1())["nested_key1"].set_foo("nested_foo");
714   out.add_map3()->set_value("one one one");
715   out.add_map4()->set_value("bool");
716 
717   ow_.StartObject("")
718       ->StartObject("map1")
719       ->StartObject("")
720       ->RenderString("foo", "foovalue")
721       ->EndObject()
722       ->EndObject()
723       ->StartObject("map2")
724       ->StartObject("")
725       ->StartObject("map1")
726       ->StartObject("nested_key1")
727       ->RenderString("foo", "nested_foo")
728       ->EndObject()
729       ->EndObject()
730       ->EndObject()
731       ->EndObject()
732       ->StartObject("map3")
733       ->RenderString("0", "one one one")
734       ->EndObject()
735       ->StartObject("map4")
736       ->RenderString("false", "bool")
737       ->EndObject()
738       ->EndObject();
739 
740   DoTest(out, MapOut::descriptor());
741 }
742 
743 class ProtostreamObjectSourceAnysTest : public ProtostreamObjectSourceTest {
744  protected:
ProtostreamObjectSourceAnysTest()745   ProtostreamObjectSourceAnysTest() {
746     helper_.ResetTypeInfo({AnyOut::descriptor(), Book::descriptor(),
747                            google::protobuf::Any::descriptor()});
748   }
749 };
750 
751 INSTANTIATE_TEST_SUITE_P(DifferentTypeInfoSourceTest,
752                          ProtostreamObjectSourceAnysTest,
753                          ::testing::Values(
754                              testing::USE_TYPE_RESOLVER));
755 
756 // Tests JSON any support.
757 //
758 // This is the example expected output.
759 // {
760 //   "any": {
761 //     "@type": "type.googleapis.com/google.protobuf.testing.AnyM"
762 //     "foo": "foovalue"
763 //   }
764 // }
TEST_P(ProtostreamObjectSourceAnysTest,BasicAny)765 TEST_P(ProtostreamObjectSourceAnysTest, BasicAny) {
766   AnyOut out;
767   ::google::protobuf::Any* any = out.mutable_any();
768 
769   AnyM m;
770   m.set_foo("foovalue");
771   any->PackFrom(m);
772 
773   ow_.StartObject("")
774       ->StartObject("any")
775       ->RenderString("@type",
776                      "type.googleapis.com/proto_util_converter.testing.AnyM")
777       ->RenderString("foo", "foovalue")
778       ->EndObject()
779       ->EndObject();
780 
781   DoTest(out, AnyOut::descriptor());
782 }
783 
TEST_P(ProtostreamObjectSourceAnysTest,LowerCamelEnumOutputSnakeCase)784 TEST_P(ProtostreamObjectSourceAnysTest, LowerCamelEnumOutputSnakeCase) {
785   AnyOut out;
786   ::google::protobuf::Any* any = out.mutable_any();
787 
788   Book book;
789   book.set_type(Book::arts_and_photography);
790   any->PackFrom(book);
791 
792   UseLowerCamelForEnums();
793 
794   ow_.StartObject("")
795       ->StartObject("any")
796       ->RenderString("@type",
797                      "type.googleapis.com/proto_util_converter.testing.Book")
798       ->RenderString("type", "artsAndPhotography")
799       ->EndObject()
800       ->EndObject();
801 
802   DoTest(out, AnyOut::descriptor());
803 }
804 
TEST_P(ProtostreamObjectSourceAnysTest,UseIntsForEnumsTest)805 TEST_P(ProtostreamObjectSourceAnysTest, UseIntsForEnumsTest) {
806   AnyOut out;
807   ::google::protobuf::Any* any = out.mutable_any();
808 
809   Book book;
810   book.set_type(Book::ACTION_AND_ADVENTURE);
811   any->PackFrom(book);
812 
813   UseIntsForEnums();
814 
815   ow_.StartObject("")
816       ->StartObject("any")
817       ->RenderString("@type",
818                      "type.googleapis.com/proto_util_converter.testing.Book")
819       ->RenderInt32("type", 3)
820       ->EndObject()
821       ->EndObject();
822 
823   DoTest(out, AnyOut::descriptor());
824 }
825 
TEST_P(ProtostreamObjectSourceAnysTest,UsePreserveProtoFieldNames)826 TEST_P(ProtostreamObjectSourceAnysTest, UsePreserveProtoFieldNames) {
827   AnyOut out;
828   ::google::protobuf::Any* any = out.mutable_any();
829 
830   Book book;
831   book.set_snake_field("foo");
832   any->PackFrom(book);
833 
834   UsePreserveProtoFieldNames();
835 
836   ow_.StartObject("")
837       ->StartObject("any")
838       ->RenderString("@type",
839                      "type.googleapis.com/proto_util_converter.testing.Book")
840       ->RenderString("snake_field", "foo")
841       ->EndObject()
842       ->EndObject();
843 
844   DoTest(out, AnyOut::descriptor());
845 }
846 
TEST_P(ProtostreamObjectSourceAnysTest,RecursiveAny)847 TEST_P(ProtostreamObjectSourceAnysTest, RecursiveAny) {
848   AnyOut out;
849   ::google::protobuf::Any* any = out.mutable_any();
850   any->set_type_url("type.googleapis.com/google.protobuf.Any");
851 
852   ::google::protobuf::Any nested_any;
853   nested_any.set_type_url(
854       "type.googleapis.com/proto_util_converter.testing.AnyM");
855 
856   AnyM m;
857   m.set_foo("foovalue");
858   nested_any.set_value(m.SerializeAsString());
859 
860   any->set_value(nested_any.SerializeAsString());
861 
862   ow_.StartObject("")
863       ->StartObject("any")
864       ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
865       ->StartObject("value")
866       ->RenderString("@type",
867                      "type.googleapis.com/proto_util_converter.testing.AnyM")
868       ->RenderString("foo", "foovalue")
869       ->EndObject()
870       ->EndObject()
871       ->EndObject();
872 
873   DoTest(out, AnyOut::descriptor());
874 }
875 
TEST_P(ProtostreamObjectSourceAnysTest,DoubleRecursiveAny)876 TEST_P(ProtostreamObjectSourceAnysTest, DoubleRecursiveAny) {
877   AnyOut out;
878   ::google::protobuf::Any* any = out.mutable_any();
879   any->set_type_url("type.googleapis.com/google.protobuf.Any");
880 
881   ::google::protobuf::Any nested_any;
882   nested_any.set_type_url("type.googleapis.com/google.protobuf.Any");
883 
884   ::google::protobuf::Any second_nested_any;
885   second_nested_any.set_type_url(
886       "type.googleapis.com/proto_util_converter.testing.AnyM");
887 
888   AnyM m;
889   m.set_foo("foovalue");
890   second_nested_any.set_value(m.SerializeAsString());
891   nested_any.set_value(second_nested_any.SerializeAsString());
892   any->set_value(nested_any.SerializeAsString());
893 
894   ow_.StartObject("")
895       ->StartObject("any")
896       ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
897       ->StartObject("value")
898       ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
899       ->StartObject("value")
900       ->RenderString("@type",
901                      "type.googleapis.com/proto_util_converter.testing.AnyM")
902       ->RenderString("foo", "foovalue")
903       ->EndObject()
904       ->EndObject()
905       ->EndObject()
906       ->EndObject();
907 
908   DoTest(out, AnyOut::descriptor());
909 }
910 
TEST_P(ProtostreamObjectSourceAnysTest,EmptyAnyOutputsEmptyObject)911 TEST_P(ProtostreamObjectSourceAnysTest, EmptyAnyOutputsEmptyObject) {
912   AnyOut out;
913   out.mutable_any();
914 
915   ow_.StartObject("")->StartObject("any")->EndObject()->EndObject();
916 
917   DoTest(out, AnyOut::descriptor());
918 }
919 
TEST_P(ProtostreamObjectSourceAnysTest,EmptyWithTypeAndNoValueOutputsType)920 TEST_P(ProtostreamObjectSourceAnysTest, EmptyWithTypeAndNoValueOutputsType) {
921   AnyOut out;
922   out.mutable_any()->set_type_url("foo.googleapis.com/my.Type");
923 
924   ow_.StartObject("")
925       ->StartObject("any")
926       ->RenderString("@type", "foo.googleapis.com/my.Type")
927       ->EndObject()
928       ->EndObject();
929 
930   DoTest(out, AnyOut::descriptor());
931 }
932 
TEST_P(ProtostreamObjectSourceAnysTest,MissingTypeUrlError)933 TEST_P(ProtostreamObjectSourceAnysTest, MissingTypeUrlError) {
934   AnyOut out;
935   ::google::protobuf::Any* any = out.mutable_any();
936 
937   AnyM m;
938   m.set_foo("foovalue");
939   any->set_value(m.SerializeAsString());
940 
941   // We start the "AnyOut" part and then fail when we hit the Any object.
942   ow_.StartObject("");
943 
944   Status status = ExecuteTest(out, AnyOut::descriptor());
945   EXPECT_EQ(util::error::INTERNAL, status.code());
946 }
947 
TEST_P(ProtostreamObjectSourceAnysTest,UnknownTypeServiceError)948 TEST_P(ProtostreamObjectSourceAnysTest, UnknownTypeServiceError) {
949   AnyOut out;
950   ::google::protobuf::Any* any = out.mutable_any();
951   any->set_type_url("foo.googleapis.com/my.own.Type");
952 
953   AnyM m;
954   m.set_foo("foovalue");
955   any->set_value(m.SerializeAsString());
956 
957   // We start the "AnyOut" part and then fail when we hit the Any object.
958   ow_.StartObject("");
959 
960   Status status = ExecuteTest(out, AnyOut::descriptor());
961   EXPECT_EQ(util::error::INTERNAL, status.code());
962 }
963 
TEST_P(ProtostreamObjectSourceAnysTest,UnknownTypeError)964 TEST_P(ProtostreamObjectSourceAnysTest, UnknownTypeError) {
965   AnyOut out;
966   ::google::protobuf::Any* any = out.mutable_any();
967   any->set_type_url("type.googleapis.com/unknown.Type");
968 
969   AnyM m;
970   m.set_foo("foovalue");
971   any->set_value(m.SerializeAsString());
972 
973   // We start the "AnyOut" part and then fail when we hit the Any object.
974   ow_.StartObject("");
975 
976   Status status = ExecuteTest(out, AnyOut::descriptor());
977   EXPECT_EQ(util::error::INTERNAL, status.code());
978 }
979 
980 class ProtostreamObjectSourceStructTest : public ProtostreamObjectSourceTest {
981  protected:
ProtostreamObjectSourceStructTest()982   ProtostreamObjectSourceStructTest() {
983     helper_.ResetTypeInfo(StructType::descriptor(),
984                           google::protobuf::Struct::descriptor());
985   }
986 };
987 
988 INSTANTIATE_TEST_SUITE_P(DifferentTypeInfoSourceTest,
989                          ProtostreamObjectSourceStructTest,
990                          ::testing::Values(
991                              testing::USE_TYPE_RESOLVER));
992 
993 // Tests struct
994 //
995 //  "object": {
996 //    "k1": 123,
997 //    "k2": true
998 //  }
TEST_P(ProtostreamObjectSourceStructTest,StructRenderSuccess)999 TEST_P(ProtostreamObjectSourceStructTest, StructRenderSuccess) {
1000   StructType out;
1001   google::protobuf::Struct* s = out.mutable_object();
1002   s->mutable_fields()->operator[]("k1").set_number_value(123);
1003   s->mutable_fields()->operator[]("k2").set_bool_value(true);
1004 
1005   ow_.StartObject("")
1006       ->StartObject("object")
1007       ->RenderDouble("k1", 123)
1008       ->RenderBool("k2", true)
1009       ->EndObject()
1010       ->EndObject();
1011 
1012   DoTest(out, StructType::descriptor());
1013 }
1014 
TEST_P(ProtostreamObjectSourceStructTest,MissingValueSkipsField)1015 TEST_P(ProtostreamObjectSourceStructTest, MissingValueSkipsField) {
1016   StructType out;
1017   google::protobuf::Struct* s = out.mutable_object();
1018   s->mutable_fields()->operator[]("k1");
1019 
1020   ow_.StartObject("")->StartObject("object")->EndObject()->EndObject();
1021 
1022   DoTest(out, StructType::descriptor());
1023 }
1024 
1025 class ProtostreamObjectSourceFieldMaskTest
1026     : public ProtostreamObjectSourceTest {
1027  protected:
ProtostreamObjectSourceFieldMaskTest()1028   ProtostreamObjectSourceFieldMaskTest() {
1029     helper_.ResetTypeInfo(FieldMaskTest::descriptor(),
1030                           google::protobuf::FieldMask::descriptor());
1031   }
1032 };
1033 
1034 INSTANTIATE_TEST_SUITE_P(DifferentTypeInfoSourceTest,
1035                          ProtostreamObjectSourceFieldMaskTest,
1036                          ::testing::Values(
1037                              testing::USE_TYPE_RESOLVER));
1038 
TEST_P(ProtostreamObjectSourceFieldMaskTest,FieldMaskRenderSuccess)1039 TEST_P(ProtostreamObjectSourceFieldMaskTest, FieldMaskRenderSuccess) {
1040   FieldMaskTest out;
1041   out.set_id("1");
1042   out.mutable_single_mask()->add_paths("path1");
1043   out.mutable_single_mask()->add_paths("snake_case_path2");
1044   ::google::protobuf::FieldMask* mask = out.add_repeated_mask();
1045   mask->add_paths("path3");
1046   mask = out.add_repeated_mask();
1047   mask->add_paths("snake_case_path4");
1048   mask->add_paths("path5");
1049   NestedFieldMask* nested = out.add_nested_mask();
1050   nested->set_data("data");
1051   nested->mutable_single_mask()->add_paths("nested.path1");
1052   nested->mutable_single_mask()->add_paths("nested_field.snake_case_path2");
1053   mask = nested->add_repeated_mask();
1054   mask->add_paths("nested_field.path3");
1055   mask->add_paths("nested.snake_case_path4");
1056   mask = nested->add_repeated_mask();
1057   mask->add_paths("nested.path5");
1058   mask = nested->add_repeated_mask();
1059   mask->add_paths(
1060       "snake_case.map_field[\"map_key_should_be_ignored\"].nested_snake_case."
1061       "map_field[\"map_key_sho\\\"uld_be_ignored\"]");
1062 
1063   ow_.StartObject("")
1064       ->RenderString("id", "1")
1065       ->RenderString("singleMask", "path1,snakeCasePath2")
1066       ->StartList("repeatedMask")
1067       ->RenderString("", "path3")
1068       ->RenderString("", "snakeCasePath4,path5")
1069       ->EndList()
1070       ->StartList("nestedMask")
1071       ->StartObject("")
1072       ->RenderString("data", "data")
1073       ->RenderString("singleMask", "nested.path1,nestedField.snakeCasePath2")
1074       ->StartList("repeatedMask")
1075       ->RenderString("", "nestedField.path3,nested.snakeCasePath4")
1076       ->RenderString("", "nested.path5")
1077       ->RenderString("",
1078                      "snakeCase.mapField[\"map_key_should_be_ignored\"]."
1079                      "nestedSnakeCase.mapField[\"map_key_sho\\\"uld_be_"
1080                      "ignored\"]")
1081       ->EndList()
1082       ->EndObject()
1083       ->EndList()
1084       ->EndObject();
1085 
1086   DoTest(out, FieldMaskTest::descriptor());
1087 }
1088 
1089 class ProtostreamObjectSourceTimestampTest
1090     : public ProtostreamObjectSourceTest {
1091  protected:
ProtostreamObjectSourceTimestampTest()1092   ProtostreamObjectSourceTimestampTest() {
1093     helper_.ResetTypeInfo(TimestampDuration::descriptor());
1094   }
1095 };
1096 
1097 INSTANTIATE_TEST_SUITE_P(DifferentTypeInfoSourceTest,
1098                          ProtostreamObjectSourceTimestampTest,
1099                          ::testing::Values(
1100                              testing::USE_TYPE_RESOLVER));
1101 
TEST_P(ProtostreamObjectSourceTimestampTest,InvalidTimestampBelowMinTest)1102 TEST_P(ProtostreamObjectSourceTimestampTest, InvalidTimestampBelowMinTest) {
1103   TimestampDuration out;
1104   google::protobuf::Timestamp* ts = out.mutable_ts();
1105   // Min allowed seconds - 1
1106   ts->set_seconds(kTimestampMinSeconds - 1);
1107   ow_.StartObject("");
1108 
1109   Status status = ExecuteTest(out, TimestampDuration::descriptor());
1110   EXPECT_EQ(util::error::INTERNAL, status.code());
1111 }
1112 
TEST_P(ProtostreamObjectSourceTimestampTest,InvalidTimestampAboveMaxTest)1113 TEST_P(ProtostreamObjectSourceTimestampTest, InvalidTimestampAboveMaxTest) {
1114   TimestampDuration out;
1115   google::protobuf::Timestamp* ts = out.mutable_ts();
1116   // Max allowed seconds + 1
1117   ts->set_seconds(kTimestampMaxSeconds + 1);
1118   ow_.StartObject("");
1119 
1120   Status status = ExecuteTest(out, TimestampDuration::descriptor());
1121   EXPECT_EQ(util::error::INTERNAL, status.code());
1122 }
1123 
TEST_P(ProtostreamObjectSourceTimestampTest,InvalidDurationBelowMinTest)1124 TEST_P(ProtostreamObjectSourceTimestampTest, InvalidDurationBelowMinTest) {
1125   TimestampDuration out;
1126   google::protobuf::Duration* dur = out.mutable_dur();
1127   // Min allowed seconds - 1
1128   dur->set_seconds(kDurationMinSeconds - 1);
1129   ow_.StartObject("");
1130 
1131   Status status = ExecuteTest(out, TimestampDuration::descriptor());
1132   EXPECT_EQ(util::error::INTERNAL, status.code());
1133 }
1134 
TEST_P(ProtostreamObjectSourceTimestampTest,InvalidDurationAboveMaxTest)1135 TEST_P(ProtostreamObjectSourceTimestampTest, InvalidDurationAboveMaxTest) {
1136   TimestampDuration out;
1137   google::protobuf::Duration* dur = out.mutable_dur();
1138   // Min allowed seconds + 1
1139   dur->set_seconds(kDurationMaxSeconds + 1);
1140   ow_.StartObject("");
1141 
1142   Status status = ExecuteTest(out, TimestampDuration::descriptor());
1143   EXPECT_EQ(util::error::INTERNAL, status.code());
1144 }
1145 
TEST_P(ProtostreamObjectSourceTimestampTest,TimestampDurationDefaultValue)1146 TEST_P(ProtostreamObjectSourceTimestampTest, TimestampDurationDefaultValue) {
1147   TimestampDuration out;
1148   out.mutable_ts()->set_seconds(0);
1149   out.mutable_dur()->set_seconds(0);
1150 
1151   ow_.StartObject("")
1152       ->RenderString("ts", "1970-01-01T00:00:00Z")
1153       ->RenderString("dur", "0s")
1154       ->EndObject();
1155 
1156   DoTest(out, TimestampDuration::descriptor());
1157 }
1158 
1159 
1160 
1161 }  // namespace converter
1162 }  // namespace util
1163 }  // namespace protobuf
1164 }  // namespace google
1165