• 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_objectwriter.h>
32 
33 #include <stddef.h>  // For size_t
34 
35 #include <google/protobuf/field_mask.pb.h>
36 #include <google/protobuf/timestamp.pb.h>
37 #include <google/protobuf/type.pb.h>
38 #include <google/protobuf/wrappers.pb.h>
39 #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
40 #include <google/protobuf/descriptor.pb.h>
41 #include <google/protobuf/descriptor.h>
42 #include <google/protobuf/dynamic_message.h>
43 #include <google/protobuf/message.h>
44 #include <google/protobuf/util/internal/mock_error_listener.h>
45 #include <google/protobuf/util/internal/testdata/anys.pb.h>
46 #include <google/protobuf/util/internal/testdata/books.pb.h>
47 #include <google/protobuf/util/internal/testdata/field_mask.pb.h>
48 #include <google/protobuf/util/internal/testdata/maps.pb.h>
49 #include <google/protobuf/util/internal/testdata/oneofs.pb.h>
50 #include <google/protobuf/util/internal/testdata/proto3.pb.h>
51 #include <google/protobuf/util/internal/testdata/struct.pb.h>
52 #include <google/protobuf/util/internal/testdata/timestamp_duration.pb.h>
53 #include <google/protobuf/util/internal/testdata/wrappers.pb.h>
54 #include <google/protobuf/util/internal/type_info_test_helper.h>
55 #include <google/protobuf/util/internal/constants.h>
56 #include <google/protobuf/util/message_differencer.h>
57 #include <google/protobuf/util/type_resolver_util.h>
58 #include <google/protobuf/stubs/bytestream.h>
59 #include <google/protobuf/stubs/strutil.h>
60 #include <gtest/gtest.h>
61 
62 
63 namespace google {
64 namespace protobuf {
65 namespace util {
66 namespace converter {
67 
68 
69 using proto_util_converter::testing::AnyM;
70 using proto_util_converter::testing::AnyOut;
71 using proto_util_converter::testing::Author;
72 using proto_util_converter::testing::Book;
73 using proto_util_converter::testing::FieldMaskTest;
74 using proto_util_converter::testing::Int32Wrapper;
75 using proto_util_converter::testing::MapIn;
76 using proto_util_converter::testing::Primitive;
77 using proto_util_converter::testing::Proto3Message;
78 using proto_util_converter::testing::Publisher;
79 using proto_util_converter::testing::StructType;
80 using proto_util_converter::testing::TestJsonName1;
81 using proto_util_converter::testing::TestJsonName2;
82 using proto_util_converter::testing::TimestampDuration;
83 using proto_util_converter::testing::ValueWrapper;
84 using proto_util_converter::testing::oneofs::OneOfsRequest;
85 using strings::GrowingArrayByteSink;
86 using ::testing::_;
87 using ::testing::Args;
88 
89 
90 namespace {
GetTypeUrl(const Descriptor * descriptor)91 std::string GetTypeUrl(const Descriptor* descriptor) {
92   return std::string(kTypeServiceBaseUrl) + "/" + descriptor->full_name();
93 }
94 }  // namespace
95 
96 class BaseProtoStreamObjectWriterTest
97     : public ::testing::TestWithParam<testing::TypeInfoSource> {
98  protected:
BaseProtoStreamObjectWriterTest()99   BaseProtoStreamObjectWriterTest()
100       : helper_(GetParam()),
101         listener_(),
102         output_(new GrowingArrayByteSink(1000)),
103         ow_() {}
104 
BaseProtoStreamObjectWriterTest(const Descriptor * descriptor)105   explicit BaseProtoStreamObjectWriterTest(const Descriptor* descriptor)
106       : helper_(GetParam()),
107         listener_(),
108         output_(new GrowingArrayByteSink(1000)),
109         ow_() {
110     std::vector<const Descriptor*> descriptors;
111     descriptors.push_back(descriptor);
112     ResetTypeInfo(descriptors);
113   }
114 
BaseProtoStreamObjectWriterTest(std::vector<const Descriptor * > descriptors)115   explicit BaseProtoStreamObjectWriterTest(
116       std::vector<const Descriptor*> descriptors)
117       : helper_(GetParam()),
118         listener_(),
119         output_(new GrowingArrayByteSink(1000)),
120         ow_() {
121     ResetTypeInfo(descriptors);
122   }
123 
ResetTypeInfo(std::vector<const Descriptor * > descriptors)124   void ResetTypeInfo(std::vector<const Descriptor*> descriptors) {
125     GOOGLE_CHECK(!descriptors.empty()) << "Must have at least one descriptor!";
126     helper_.ResetTypeInfo(descriptors);
127     ow_.reset(helper_.NewProtoWriter(GetTypeUrl(descriptors[0]), output_.get(),
128                                      &listener_, options_));
129   }
130 
ResetTypeInfo(const Descriptor * descriptor)131   void ResetTypeInfo(const Descriptor* descriptor) {
132     std::vector<const Descriptor*> descriptors;
133     descriptors.push_back(descriptor);
134     ResetTypeInfo(descriptors);
135   }
136 
~BaseProtoStreamObjectWriterTest()137   virtual ~BaseProtoStreamObjectWriterTest() {}
138 
CheckOutput(const Message & expected,int expected_length)139   void CheckOutput(const Message& expected, int expected_length) {
140     size_t nbytes;
141     std::unique_ptr<char[]> buffer(output_->GetBuffer(&nbytes));
142     if (expected_length >= 0) {
143       EXPECT_EQ(expected_length, nbytes);
144     }
145     std::string str(buffer.get(), nbytes);
146 
147     std::stringbuf str_buf(str, std::ios_base::in);
148     std::istream istream(&str_buf);
149     std::unique_ptr<Message> message(expected.New());
150     message->ParsePartialFromIstream(&istream);
151 
152     if (!MessageDifferencer::Equivalent(expected, *message)) {
153       EXPECT_EQ(expected.DebugString(), message->DebugString());
154     }
155   }
156 
CheckOutput(const Message & expected)157   void CheckOutput(const Message& expected) { CheckOutput(expected, -1); }
158 
159   testing::TypeInfoTestHelper helper_;
160   MockErrorListener listener_;
161   std::unique_ptr<GrowingArrayByteSink> output_;
162   std::unique_ptr<ProtoStreamObjectWriter> ow_;
163   ProtoStreamObjectWriter::Options options_;
164 };
165 
166 MATCHER_P(HasObjectLocation, expected,
167           "Verifies the expected object location") {
168   std::string actual = std::get<0>(arg).ToString();
169   if (actual == expected) return true;
170   *result_listener << "actual location is: " << actual;
171   return false;
172 }
173 
174 class ProtoStreamObjectWriterTest : public BaseProtoStreamObjectWriterTest {
175  protected:
ProtoStreamObjectWriterTest()176   ProtoStreamObjectWriterTest()
177       : BaseProtoStreamObjectWriterTest(Book::descriptor()) {}
178 
ResetProtoWriter()179   void ResetProtoWriter() { ResetTypeInfo(Book::descriptor()); }
180 
~ProtoStreamObjectWriterTest()181   virtual ~ProtoStreamObjectWriterTest() {}
182 };
183 
184 INSTANTIATE_TEST_SUITE_P(DifferentTypeInfoSourceTest,
185                          ProtoStreamObjectWriterTest,
186                          ::testing::Values(
187                              testing::USE_TYPE_RESOLVER));
188 
TEST_P(ProtoStreamObjectWriterTest,EmptyObject)189 TEST_P(ProtoStreamObjectWriterTest, EmptyObject) {
190   Book empty;
191   ow_->StartObject("")->EndObject();
192   CheckOutput(empty, 0);
193 }
194 
TEST_P(ProtoStreamObjectWriterTest,SimpleObject)195 TEST_P(ProtoStreamObjectWriterTest, SimpleObject) {
196   std::string content("My content");
197 
198   Book book;
199   book.set_title("My Title");
200   book.set_length(222);
201   book.set_content(content);
202 
203   ow_->StartObject("")
204       ->RenderString("title", "My Title")
205       ->RenderInt32("length", 222)
206       ->RenderBytes("content", content)
207       ->EndObject();
208   CheckOutput(book);
209 }
210 
TEST_P(ProtoStreamObjectWriterTest,SimpleMessage)211 TEST_P(ProtoStreamObjectWriterTest, SimpleMessage) {
212   Book book;
213   book.set_title("Some Book");
214   book.set_length(102);
215   Publisher* publisher = book.mutable_publisher();
216   publisher->set_name("My Publisher");
217   Author* robert = book.mutable_author();
218   robert->set_alive(true);
219   robert->set_name("robert");
220   robert->add_pseudonym("bob");
221   robert->add_pseudonym("bobby");
222   robert->add_friend_()->set_name("john");
223 
224   ow_->StartObject("")
225       ->RenderString("title", "Some Book")
226       ->RenderInt32("length", 102)
227       ->StartObject("publisher")
228       ->RenderString("name", "My Publisher")
229       ->EndObject()
230       ->StartObject("author")
231       ->RenderBool("alive", true)
232       ->RenderString("name", "robert")
233       ->StartList("pseudonym")
234       ->RenderString("", "bob")
235       ->RenderString("", "bobby")
236       ->EndList()
237       ->StartList("friend")
238       ->StartObject("")
239       ->RenderString("name", "john")
240       ->EndObject()
241       ->EndList()
242       ->EndObject()
243       ->EndObject();
244   CheckOutput(book);
245 }
246 
TEST_P(ProtoStreamObjectWriterTest,CustomJsonName)247 TEST_P(ProtoStreamObjectWriterTest, CustomJsonName) {
248   Book book;
249   Author* robert = book.mutable_author();
250   robert->set_id(12345);
251   robert->set_name("robert");
252 
253   ow_->StartObject("")
254       ->StartObject("author")
255       ->RenderUint64("@id", 12345)
256       ->RenderString("name", "robert")
257       ->EndObject()
258       ->EndObject();
259   CheckOutput(book);
260 }
261 
262 // Test that two messages can have different fields mapped to the same JSON
263 // name. See: https://github.com/protocolbuffers/protobuf/issues/1415
TEST_P(ProtoStreamObjectWriterTest,ConflictingJsonName)264 TEST_P(ProtoStreamObjectWriterTest, ConflictingJsonName) {
265   ResetTypeInfo(TestJsonName1::descriptor());
266   TestJsonName1 message1;
267   message1.set_one_value(12345);
268   ow_->StartObject("")->RenderInt32("value", 12345)->EndObject();
269   CheckOutput(message1);
270 
271   ResetTypeInfo(TestJsonName2::descriptor());
272   TestJsonName2 message2;
273   message2.set_another_value(12345);
274   ow_->StartObject("")->RenderInt32("value", 12345)->EndObject();
275   CheckOutput(message2);
276 }
277 
278 
TEST_P(ProtoStreamObjectWriterTest,IntEnumValuesAreAccepted)279 TEST_P(ProtoStreamObjectWriterTest, IntEnumValuesAreAccepted) {
280   Book book;
281   book.set_title("Some Book");
282   book.set_type(proto_util_converter::testing::Book::KIDS);
283   Author* robert = book.mutable_author();
284   robert->set_name("robert");
285 
286   ow_->StartObject("")
287       ->RenderString("title", "Some Book")
288       ->RenderString("type", "2")
289       ->StartObject("author")
290       ->RenderString("name", "robert")
291       ->EndObject()
292       ->EndObject();
293   CheckOutput(book);
294 }
295 
TEST_P(ProtoStreamObjectWriterTest,EnumValuesWithDifferentCaseIsRejected)296 TEST_P(ProtoStreamObjectWriterTest, EnumValuesWithDifferentCaseIsRejected) {
297   Book book;
298   book.set_title("Some Book");
299   Author* robert = book.mutable_author();
300   robert->set_name("robert");
301 
302   options_.case_insensitive_enum_parsing = false;
303   ResetProtoWriter();
304 
305   ow_->StartObject("")
306       ->RenderString("title", "Some Book")
307       ->RenderString("type", "action_and_adventure")
308       ->StartObject("author")
309       ->RenderString("name", "robert")
310       ->EndObject()
311       ->EndObject();
312   CheckOutput(book);
313 }
314 
TEST_P(ProtoStreamObjectWriterTest,EnumValuesWithSameCaseIsAccepted)315 TEST_P(ProtoStreamObjectWriterTest, EnumValuesWithSameCaseIsAccepted) {
316   Book book;
317   book.set_title("Some Book");
318   book.set_type(proto_util_converter::testing::Book::ACTION_AND_ADVENTURE);
319   Author* robert = book.mutable_author();
320   robert->set_name("robert");
321 
322   options_.case_insensitive_enum_parsing = false;
323   ResetProtoWriter();
324 
325   ow_->StartObject("")
326       ->RenderString("title", "Some Book")
327       ->RenderString("type", "ACTION_AND_ADVENTURE")
328       ->StartObject("author")
329       ->RenderString("name", "robert")
330       ->EndObject()
331       ->EndObject();
332   CheckOutput(book);
333 }
334 
TEST_P(ProtoStreamObjectWriterTest,EnumValuesWithDifferentCaseIsAccepted)335 TEST_P(ProtoStreamObjectWriterTest, EnumValuesWithDifferentCaseIsAccepted) {
336   Book book;
337   book.set_title("Some Book");
338   book.set_type(proto_util_converter::testing::Book::ACTION_AND_ADVENTURE);
339   Author* robert = book.mutable_author();
340   robert->set_name("robert");
341 
342   options_.case_insensitive_enum_parsing = true;
343   ResetProtoWriter();
344 
345   ow_->StartObject("")
346       ->RenderString("title", "Some Book")
347       ->RenderString("type", "action_AND_adventure")
348       ->StartObject("author")
349       ->RenderString("name", "robert")
350       ->EndObject()
351       ->EndObject();
352   CheckOutput(book);
353 }
354 
TEST_P(ProtoStreamObjectWriterTest,EnumValuesWithoutUnderscoreAreAccepted)355 TEST_P(ProtoStreamObjectWriterTest, EnumValuesWithoutUnderscoreAreAccepted) {
356   Book book;
357   book.set_title("Some Book");
358   book.set_type(proto_util_converter::testing::Book::ACTION_AND_ADVENTURE);
359   Author* robert = book.mutable_author();
360   robert->set_name("robert");
361 
362   options_.use_lower_camel_for_enums = true;
363   ResetProtoWriter();
364 
365   ow_->StartObject("")
366       ->RenderString("title", "Some Book")
367       ->RenderString("type", "ACTIONANDADVENTURE")
368       ->StartObject("author")
369       ->RenderString("name", "robert")
370       ->EndObject()
371       ->EndObject();
372   CheckOutput(book);
373 }
374 
TEST_P(ProtoStreamObjectWriterTest,EnumValuesInCamelCaseAreAccepted)375 TEST_P(ProtoStreamObjectWriterTest, EnumValuesInCamelCaseAreAccepted) {
376   Book book;
377   book.set_title("Some Book");
378   book.set_type(proto_util_converter::testing::Book::ACTION_AND_ADVENTURE);
379   Author* robert = book.mutable_author();
380   robert->set_name("robert");
381 
382   options_.use_lower_camel_for_enums = true;
383   ResetProtoWriter();
384 
385   ow_->StartObject("")
386       ->RenderString("title", "Some Book")
387       ->RenderString("type", "actionAndAdventure")
388       ->StartObject("author")
389       ->RenderString("name", "robert")
390       ->EndObject()
391       ->EndObject();
392   CheckOutput(book);
393 }
394 
TEST_P(ProtoStreamObjectWriterTest,EnumValuesInCamelCaseRemoveDashAndUnderscoreAreAccepted)395 TEST_P(ProtoStreamObjectWriterTest,
396        EnumValuesInCamelCaseRemoveDashAndUnderscoreAreAccepted) {
397   Book book;
398   book.set_title("Some Book");
399   book.set_type(proto_util_converter::testing::Book::ACTION_AND_ADVENTURE);
400   Author* robert = book.mutable_author();
401   robert->set_name("robert");
402 
403   options_.use_lower_camel_for_enums = true;
404   options_.case_insensitive_enum_parsing = false;
405   ResetProtoWriter();
406 
407   ow_->StartObject("")
408       ->RenderString("title", "Some Book")
409       ->RenderString("type", "action-And_Adventure")
410       ->StartObject("author")
411       ->RenderString("name", "robert")
412       ->EndObject()
413       ->EndObject();
414   CheckOutput(book);
415 }
416 
TEST_P(ProtoStreamObjectWriterTest,EnumValuesInCamelCaseWithNameNotUppercaseAreAccepted)417 TEST_P(ProtoStreamObjectWriterTest,
418        EnumValuesInCamelCaseWithNameNotUppercaseAreAccepted) {
419   Book book;
420   book.set_title("Some Book");
421   book.set_type(proto_util_converter::testing::Book::arts_and_photography);
422   Author* robert = book.mutable_author();
423   robert->set_name("robert");
424 
425   options_.use_lower_camel_for_enums = true;
426   ResetProtoWriter();
427 
428   ow_->StartObject("")
429       ->RenderString("title", "Some Book")
430       ->RenderString("type", "artsAndPhotography")
431       ->StartObject("author")
432       ->RenderString("name", "robert")
433       ->EndObject()
434       ->EndObject();
435   CheckOutput(book);
436 }
437 
TEST_P(ProtoStreamObjectWriterTest,PrimitiveFromStringConversion)438 TEST_P(ProtoStreamObjectWriterTest, PrimitiveFromStringConversion) {
439   Primitive full;
440   full.set_fix32(101);
441   full.set_u32(102);
442   full.set_i32(-103);
443   full.set_sf32(-104);
444   full.set_s32(-105);
445   full.set_fix64(40000000001L);
446   full.set_u64(40000000002L);
447   full.set_i64(-40000000003L);
448   full.set_sf64(-40000000004L);
449   full.set_s64(-40000000005L);
450   full.set_str("string1");
451   full.set_bytes("Some Bytes");
452   full.set_float_(3.14f);
453   full.set_double_(-4.05L);
454   full.set_bool_(true);
455   full.add_rep_fix32(201);
456   full.add_rep_u32(202);
457   full.add_rep_i32(-203);
458   full.add_rep_sf32(-204);
459   full.add_rep_s32(-205);
460   full.add_rep_fix64(80000000001L);
461   full.add_rep_u64(80000000002L);
462   full.add_rep_i64(-80000000003L);
463   full.add_rep_sf64(-80000000004L);
464   full.add_rep_s64(-80000000005L);
465   full.add_rep_str("string2");
466   full.add_rep_bytes("More Bytes");
467   full.add_rep_float(6.14f);
468   full.add_rep_double(-8.05L);
469   full.add_rep_bool(false);
470 
471   ResetTypeInfo(Primitive::descriptor());
472 
473   ow_->StartObject("")
474       ->RenderString("fix32", "101")
475       ->RenderString("u32", "102")
476       ->RenderString("i32", "-103")
477       ->RenderString("sf32", "-104")
478       ->RenderString("s32", "-105")
479       ->RenderString("fix64", "40000000001")
480       ->RenderString("u64", "40000000002")
481       ->RenderString("i64", "-40000000003")
482       ->RenderString("sf64", "-40000000004")
483       ->RenderString("s64", "-40000000005")
484       ->RenderString("str", "string1")
485       ->RenderString("bytes", "U29tZSBCeXRlcw==")  // "Some Bytes"
486       ->RenderString("float", "3.14")
487       ->RenderString("double", "-4.05")
488       ->RenderString("bool", "true")
489       ->StartList("rep_fix32")
490       ->RenderString("", "201")
491       ->EndList()
492       ->StartList("rep_u32")
493       ->RenderString("", "202")
494       ->EndList()
495       ->StartList("rep_i32")
496       ->RenderString("", "-203")
497       ->EndList()
498       ->StartList("rep_sf32")
499       ->RenderString("", "-204")
500       ->EndList()
501       ->StartList("rep_s32")
502       ->RenderString("", "-205")
503       ->EndList()
504       ->StartList("rep_fix64")
505       ->RenderString("", "80000000001")
506       ->EndList()
507       ->StartList("rep_u64")
508       ->RenderString("", "80000000002")
509       ->EndList()
510       ->StartList("rep_i64")
511       ->RenderString("", "-80000000003")
512       ->EndList()
513       ->StartList("rep_sf64")
514       ->RenderString("", "-80000000004")
515       ->EndList()
516       ->StartList("rep_s64")
517       ->RenderString("", "-80000000005")
518       ->EndList()
519       ->StartList("rep_str")
520       ->RenderString("", "string2")
521       ->EndList()
522       ->StartList("rep_bytes")
523       ->RenderString("", "TW9yZSBCeXRlcw==")  // "More Bytes"
524       ->EndList()
525       ->StartList("rep_float")
526       ->RenderString("", "6.14")
527       ->EndList()
528       ->StartList("rep_double")
529       ->RenderString("", "-8.05")
530       ->EndList()
531       ->StartList("rep_bool")
532       ->RenderString("", "false")
533       ->EndList()
534       ->EndObject();
535   CheckOutput(full);
536 }
537 
TEST_P(ProtoStreamObjectWriterTest,InfinityInputTest)538 TEST_P(ProtoStreamObjectWriterTest, InfinityInputTest) {
539   Primitive full;
540   full.set_double_(std::numeric_limits<double>::infinity());
541   full.set_float_(std::numeric_limits<float>::infinity());
542   full.set_str("-Infinity");
543 
544   ResetTypeInfo(Primitive::descriptor());
545 
546   EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_INT32"),
547                                       StringPiece("\"Infinity\"")))
548       .With(Args<0>(HasObjectLocation("i32")));
549   EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_UINT32"),
550                                       StringPiece("\"Infinity\"")))
551       .With(Args<0>(HasObjectLocation("u32")));
552   EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_SFIXED64"),
553                                       StringPiece("\"-Infinity\"")))
554       .With(Args<0>(HasObjectLocation("sf64")));
555   EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_BOOL"),
556                                       StringPiece("\"Infinity\"")))
557       .With(Args<0>(HasObjectLocation("bool")));
558 
559   ow_->StartObject("")
560       ->RenderString("double", "Infinity")
561       ->RenderString("float", "Infinity")
562       ->RenderString("i32", "Infinity")
563       ->RenderString("u32", "Infinity")
564       ->RenderString("sf64", "-Infinity")
565       ->RenderString("str", "-Infinity")
566       ->RenderString("bool", "Infinity")
567       ->EndObject();
568   CheckOutput(full);
569 }
570 
TEST_P(ProtoStreamObjectWriterTest,NaNInputTest)571 TEST_P(ProtoStreamObjectWriterTest, NaNInputTest) {
572   Primitive full;
573   full.set_double_(std::numeric_limits<double>::quiet_NaN());
574   full.set_float_(std::numeric_limits<float>::quiet_NaN());
575   full.set_str("NaN");
576 
577   ResetTypeInfo(Primitive::descriptor());
578 
579   EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_INT32"),
580                                       StringPiece("\"NaN\"")))
581       .With(Args<0>(HasObjectLocation("i32")));
582   EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_UINT32"),
583                                       StringPiece("\"NaN\"")))
584       .With(Args<0>(HasObjectLocation("u32")));
585   EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_SFIXED64"),
586                                       StringPiece("\"NaN\"")))
587       .With(Args<0>(HasObjectLocation("sf64")));
588   EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_BOOL"),
589                                       StringPiece("\"NaN\"")))
590       .With(Args<0>(HasObjectLocation("bool")));
591 
592   ow_->StartObject("")
593       ->RenderString("double", "NaN")
594       ->RenderString("float", "NaN")
595       ->RenderString("i32", "NaN")
596       ->RenderString("u32", "NaN")
597       ->RenderString("sf64", "NaN")
598       ->RenderString("str", "NaN")
599       ->RenderString("bool", "NaN")
600       ->EndObject();
601 
602   CheckOutput(full);
603 }
604 
TEST_P(ProtoStreamObjectWriterTest,ImplicitPrimitiveList)605 TEST_P(ProtoStreamObjectWriterTest, ImplicitPrimitiveList) {
606   Book expected;
607   Author* author = expected.mutable_author();
608   author->set_name("The Author");
609   author->add_pseudonym("first");
610   author->add_pseudonym("second");
611 
612   ow_->StartObject("")
613       ->StartObject("author")
614       ->RenderString("name", "The Author")
615       ->RenderString("pseudonym", "first")
616       ->RenderString("pseudonym", "second")
617       ->EndObject()
618       ->EndObject();
619   CheckOutput(expected);
620 }
621 
TEST_P(ProtoStreamObjectWriterTest,LastWriteWinsOnNonRepeatedPrimitiveFieldWithDuplicates)622 TEST_P(ProtoStreamObjectWriterTest,
623        LastWriteWinsOnNonRepeatedPrimitiveFieldWithDuplicates) {
624   Book expected;
625   Author* author = expected.mutable_author();
626   author->set_name("second");
627 
628   ow_->StartObject("")
629       ->StartObject("author")
630       ->RenderString("name", "first")
631       ->RenderString("name", "second")
632       ->EndObject()
633       ->EndObject();
634   CheckOutput(expected);
635 }
636 
TEST_P(ProtoStreamObjectWriterTest,ExplicitPrimitiveList)637 TEST_P(ProtoStreamObjectWriterTest, ExplicitPrimitiveList) {
638   Book expected;
639   Author* author = expected.mutable_author();
640   author->set_name("The Author");
641   author->add_pseudonym("first");
642   author->add_pseudonym("second");
643 
644   ow_->StartObject("")
645       ->StartObject("author")
646       ->RenderString("name", "The Author")
647       ->StartList("pseudonym")
648       ->RenderString("", "first")
649       ->RenderString("", "second")
650       ->EndList()
651       ->EndObject()
652       ->EndObject();
653   CheckOutput(expected);
654 }
655 
TEST_P(ProtoStreamObjectWriterTest,NonRepeatedExplicitPrimitiveList)656 TEST_P(ProtoStreamObjectWriterTest, NonRepeatedExplicitPrimitiveList) {
657   Book expected;
658   expected.set_allocated_author(new Author());
659 
660   EXPECT_CALL(
661       listener_,
662       InvalidName(_, StringPiece("name"),
663                   StringPiece(
664                       "Proto field is not repeating, cannot start list.")))
665       .With(Args<0>(HasObjectLocation("author")));
666   ow_->StartObject("")
667       ->StartObject("author")
668       ->StartList("name")
669       ->RenderString("", "first")
670       ->RenderString("", "second")
671       ->EndList()
672       ->EndObject()
673       ->EndObject();
674   CheckOutput(expected);
675 }
676 
TEST_P(ProtoStreamObjectWriterTest,ImplicitMessageList)677 TEST_P(ProtoStreamObjectWriterTest, ImplicitMessageList) {
678   Book expected;
679   Author* outer = expected.mutable_author();
680   outer->set_name("outer");
681   outer->set_alive(true);
682   Author* first = outer->add_friend_();
683   first->set_name("first");
684   Author* second = outer->add_friend_();
685   second->set_name("second");
686 
687   ow_->StartObject("")
688       ->StartObject("author")
689       ->RenderString("name", "outer")
690       ->RenderBool("alive", true)
691       ->StartObject("friend")
692       ->RenderString("name", "first")
693       ->EndObject()
694       ->StartObject("friend")
695       ->RenderString("name", "second")
696       ->EndObject()
697       ->EndObject()
698       ->EndObject();
699   CheckOutput(expected);
700 }
701 
TEST_P(ProtoStreamObjectWriterTest,LastWriteWinsOnNonRepeatedMessageFieldWithDuplicates)702 TEST_P(ProtoStreamObjectWriterTest,
703        LastWriteWinsOnNonRepeatedMessageFieldWithDuplicates) {
704   Book expected;
705   Author* author = expected.mutable_author();
706   author->set_name("The Author");
707   Publisher* publisher = expected.mutable_publisher();
708   publisher->set_name("second");
709 
710   ow_->StartObject("")
711       ->StartObject("author")
712       ->RenderString("name", "The Author")
713       ->EndObject()
714       ->StartObject("publisher")
715       ->RenderString("name", "first")
716       ->EndObject()
717       ->StartObject("publisher")
718       ->RenderString("name", "second")
719       ->EndObject()
720       ->EndObject();
721   CheckOutput(expected);
722 }
723 
TEST_P(ProtoStreamObjectWriterTest,ExplicitMessageList)724 TEST_P(ProtoStreamObjectWriterTest, ExplicitMessageList) {
725   Book expected;
726   Author* outer = expected.mutable_author();
727   outer->set_name("outer");
728   outer->set_alive(true);
729   Author* first = outer->add_friend_();
730   first->set_name("first");
731   Author* second = outer->add_friend_();
732   second->set_name("second");
733 
734   ow_->StartObject("")
735       ->StartObject("author")
736       ->RenderString("name", "outer")
737       ->RenderBool("alive", true)
738       ->StartList("friend")
739       ->StartObject("")
740       ->RenderString("name", "first")
741       ->EndObject()
742       ->StartObject("")
743       ->RenderString("name", "second")
744       ->EndObject()
745       ->EndList()
746       ->EndObject()
747       ->EndObject();
748   CheckOutput(expected);
749 }
750 
TEST_P(ProtoStreamObjectWriterTest,NonRepeatedExplicitMessageList)751 TEST_P(ProtoStreamObjectWriterTest, NonRepeatedExplicitMessageList) {
752   Book expected;
753   Author* author = expected.mutable_author();
754   author->set_name("The Author");
755 
756   EXPECT_CALL(
757       listener_,
758       InvalidName(_, StringPiece("publisher"),
759                   StringPiece(
760                       "Proto field is not repeating, cannot start list.")))
761       .With(Args<0>(HasObjectLocation("")));
762   ow_->StartObject("")
763       ->StartObject("author")
764       ->RenderString("name", "The Author")
765       ->EndObject()
766       ->StartList("publisher")
767       ->StartObject("")
768       ->RenderString("name", "first")
769       ->EndObject()
770       ->StartObject("")
771       ->RenderString("name", "second")
772       ->EndObject()
773       ->EndList()
774       ->EndObject();
775   CheckOutput(expected);
776 }
777 
TEST_P(ProtoStreamObjectWriterTest,UnknownFieldAtRoot)778 TEST_P(ProtoStreamObjectWriterTest, UnknownFieldAtRoot) {
779   Book empty;
780 
781   EXPECT_CALL(listener_, InvalidName(_, StringPiece("unknown"),
782                                      StringPiece("Cannot find field.")))
783       .With(Args<0>(HasObjectLocation("")));
784   ow_->StartObject("")->RenderString("unknown", "Nope!")->EndObject();
785   CheckOutput(empty, 0);
786 }
787 
TEST_P(ProtoStreamObjectWriterTest,UnknownFieldAtAuthorFriend)788 TEST_P(ProtoStreamObjectWriterTest, UnknownFieldAtAuthorFriend) {
789   Book expected;
790   Author* paul = expected.mutable_author();
791   paul->set_name("Paul");
792   Author* mark = paul->add_friend_();
793   mark->set_name("Mark");
794   Author* john = paul->add_friend_();
795   john->set_name("John");
796   Author* luke = paul->add_friend_();
797   luke->set_name("Luke");
798 
799   EXPECT_CALL(listener_, InvalidName(_, StringPiece("address"),
800                                      StringPiece("Cannot find field.")))
801       .With(Args<0>(HasObjectLocation("author.friend[1]")));
802   ow_->StartObject("")
803       ->StartObject("author")
804       ->RenderString("name", "Paul")
805       ->StartList("friend")
806       ->StartObject("")
807       ->RenderString("name", "Mark")
808       ->EndObject()
809       ->StartObject("")
810       ->RenderString("name", "John")
811       ->RenderString("address", "Patmos")
812       ->EndObject()
813       ->StartObject("")
814       ->RenderString("name", "Luke")
815       ->EndObject()
816       ->EndList()
817       ->EndObject()
818       ->EndObject();
819   CheckOutput(expected);
820 }
821 
TEST_P(ProtoStreamObjectWriterTest,UnknownObjectAtRoot)822 TEST_P(ProtoStreamObjectWriterTest, UnknownObjectAtRoot) {
823   Book empty;
824 
825   EXPECT_CALL(listener_, InvalidName(_, StringPiece("unknown"),
826                                      StringPiece("Cannot find field.")))
827       .With(Args<0>(HasObjectLocation("")));
828   ow_->StartObject("")->StartObject("unknown")->EndObject()->EndObject();
829   CheckOutput(empty, 0);
830 }
831 
TEST_P(ProtoStreamObjectWriterTest,UnknownObjectAtAuthor)832 TEST_P(ProtoStreamObjectWriterTest, UnknownObjectAtAuthor) {
833   Book expected;
834   Author* author = expected.mutable_author();
835   author->set_name("William");
836   author->add_pseudonym("Bill");
837 
838   EXPECT_CALL(listener_, InvalidName(_, StringPiece("wife"),
839                                      StringPiece("Cannot find field.")))
840       .With(Args<0>(HasObjectLocation("author")));
841   ow_->StartObject("")
842       ->StartObject("author")
843       ->RenderString("name", "William")
844       ->StartObject("wife")
845       ->RenderString("name", "Hilary")
846       ->EndObject()
847       ->RenderString("pseudonym", "Bill")
848       ->EndObject()
849       ->EndObject();
850   CheckOutput(expected);
851 }
852 
TEST_P(ProtoStreamObjectWriterTest,UnknownListAtRoot)853 TEST_P(ProtoStreamObjectWriterTest, UnknownListAtRoot) {
854   Book empty;
855 
856   EXPECT_CALL(listener_, InvalidName(_, StringPiece("unknown"),
857                                      StringPiece("Cannot find field.")))
858       .With(Args<0>(HasObjectLocation("")));
859   ow_->StartObject("")->StartList("unknown")->EndList()->EndObject();
860   CheckOutput(empty, 0);
861 }
862 
TEST_P(ProtoStreamObjectWriterTest,UnknownListAtPublisher)863 TEST_P(ProtoStreamObjectWriterTest, UnknownListAtPublisher) {
864   Book expected;
865   expected.set_title("Brainwashing");
866   Publisher* publisher = expected.mutable_publisher();
867   publisher->set_name("propaganda");
868 
869   EXPECT_CALL(listener_, InvalidName(_, StringPiece("alliance"),
870                                      StringPiece("Cannot find field.")))
871       .With(Args<0>(HasObjectLocation("publisher")));
872   ow_->StartObject("")
873       ->StartObject("publisher")
874       ->RenderString("name", "propaganda")
875       ->StartList("alliance")
876       ->EndList()
877       ->EndObject()
878       ->RenderString("title", "Brainwashing")
879       ->EndObject();
880   CheckOutput(expected);
881 }
882 
TEST_P(ProtoStreamObjectWriterTest,IgnoreUnknownFieldAtRoot)883 TEST_P(ProtoStreamObjectWriterTest, IgnoreUnknownFieldAtRoot) {
884   Book empty;
885 
886   options_.ignore_unknown_fields = true;
887   ResetProtoWriter();
888 
889   EXPECT_CALL(listener_, InvalidName(_, _, _)).Times(0);
890   ow_->StartObject("")->RenderString("unknown", "Nope!")->EndObject();
891   CheckOutput(empty, 0);
892 }
893 
TEST_P(ProtoStreamObjectWriterTest,IgnoreUnknownFieldAtAuthorFriend)894 TEST_P(ProtoStreamObjectWriterTest, IgnoreUnknownFieldAtAuthorFriend) {
895   Book expected;
896   Author* paul = expected.mutable_author();
897   paul->set_name("Paul");
898   Author* mark = paul->add_friend_();
899   mark->set_name("Mark");
900   Author* john = paul->add_friend_();
901   john->set_name("John");
902   Author* luke = paul->add_friend_();
903   luke->set_name("Luke");
904 
905   options_.ignore_unknown_fields = true;
906   ResetProtoWriter();
907 
908   EXPECT_CALL(listener_, InvalidName(_, _, _)).Times(0);
909   ow_->StartObject("")
910       ->StartObject("author")
911       ->RenderString("name", "Paul")
912       ->StartList("friend")
913       ->StartObject("")
914       ->RenderString("name", "Mark")
915       ->EndObject()
916       ->StartObject("")
917       ->RenderString("name", "John")
918       ->RenderString("address", "Patmos")
919       ->EndObject()
920       ->StartObject("")
921       ->RenderString("name", "Luke")
922       ->EndObject()
923       ->EndList()
924       ->EndObject()
925       ->EndObject();
926   CheckOutput(expected);
927 }
928 
TEST_P(ProtoStreamObjectWriterTest,IgnoreUnknownObjectAtRoot)929 TEST_P(ProtoStreamObjectWriterTest, IgnoreUnknownObjectAtRoot) {
930   Book empty;
931 
932   options_.ignore_unknown_fields = true;
933   ResetProtoWriter();
934 
935   EXPECT_CALL(listener_, InvalidName(_, StringPiece("unknown"),
936                                      StringPiece("Cannot find field.")))
937       .Times(0);
938   ow_->StartObject("")->StartObject("unknown")->EndObject()->EndObject();
939   CheckOutput(empty, 0);
940 }
941 
TEST_P(ProtoStreamObjectWriterTest,IgnoreUnknownObjectAtAuthor)942 TEST_P(ProtoStreamObjectWriterTest, IgnoreUnknownObjectAtAuthor) {
943   Book expected;
944   Author* author = expected.mutable_author();
945   author->set_name("William");
946   author->add_pseudonym("Bill");
947 
948   options_.ignore_unknown_fields = true;
949   ResetProtoWriter();
950 
951   EXPECT_CALL(listener_, InvalidName(_, _, _)).Times(0);
952   ow_->StartObject("")
953       ->StartObject("author")
954       ->RenderString("name", "William")
955       ->StartObject("wife")
956       ->RenderString("name", "Hilary")
957       ->EndObject()
958       ->RenderString("pseudonym", "Bill")
959       ->EndObject()
960       ->EndObject();
961   CheckOutput(expected);
962 }
963 
TEST_P(ProtoStreamObjectWriterTest,IgnoreUnknownListAtRoot)964 TEST_P(ProtoStreamObjectWriterTest, IgnoreUnknownListAtRoot) {
965   Book empty;
966 
967   options_.ignore_unknown_fields = true;
968   ResetProtoWriter();
969 
970   EXPECT_CALL(listener_, InvalidName(_, _, _)).Times(0);
971   ow_->StartObject("")->StartList("unknown")->EndList()->EndObject();
972   CheckOutput(empty, 0);
973 }
974 
TEST_P(ProtoStreamObjectWriterTest,IgnoreUnknownListAtPublisher)975 TEST_P(ProtoStreamObjectWriterTest, IgnoreUnknownListAtPublisher) {
976   Book expected;
977   expected.set_title("Brainwashing");
978   Publisher* publisher = expected.mutable_publisher();
979   publisher->set_name("propaganda");
980 
981   options_.ignore_unknown_fields = true;
982   ResetProtoWriter();
983 
984   EXPECT_CALL(listener_, InvalidName(_, _, _)).Times(0);
985   ow_->StartObject("")
986       ->StartObject("publisher")
987       ->RenderString("name", "propaganda")
988       ->StartList("alliance")
989       ->EndList()
990       ->EndObject()
991       ->RenderString("title", "Brainwashing")
992       ->EndObject();
993   CheckOutput(expected);
994 }
995 
TEST_P(ProtoStreamObjectWriterTest,IgnoreUnknownFieldsDontIgnoreUnknownEnumValues)996 TEST_P(ProtoStreamObjectWriterTest,
997        IgnoreUnknownFieldsDontIgnoreUnknownEnumValues) {
998   ResetTypeInfo(Proto3Message::descriptor());
999 
1000   Proto3Message expected;
1001   EXPECT_CALL(
1002       listener_,
1003       InvalidValue(_,
1004                    StringPiece(
1005                        "type.googleapis.com/"
1006                        "proto_util_converter.testing.Proto3Message.NestedEnum"),
1007                    StringPiece("\"someunknownvalueyouwillneverknow\"")))
1008       .With(Args<0>(HasObjectLocation("enum_value")));
1009   ow_->StartObject("")
1010       ->RenderString("enumValue", "someunknownvalueyouwillneverknow")
1011       ->EndObject();
1012   CheckOutput(expected);
1013 }
1014 
TEST_P(ProtoStreamObjectWriterTest,AcceptUnknownEnumValue)1015 TEST_P(ProtoStreamObjectWriterTest, AcceptUnknownEnumValue) {
1016   ResetTypeInfo(Proto3Message::descriptor());
1017 
1018   Proto3Message expected;
1019   expected.set_enum_value(static_cast<Proto3Message::NestedEnum>(12345));
1020 
1021   EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0);
1022   ow_->StartObject("")->RenderInt32("enumValue", 12345)->EndObject();
1023   CheckOutput(expected);
1024 }
1025 
TEST_P(ProtoStreamObjectWriterTest,MissingRequiredField)1026 TEST_P(ProtoStreamObjectWriterTest, MissingRequiredField) {
1027   Book expected;
1028   expected.set_title("My Title");
1029   expected.set_allocated_publisher(new Publisher());
1030 
1031   EXPECT_CALL(listener_, MissingField(_, StringPiece("name")))
1032       .With(Args<0>(HasObjectLocation("publisher")));
1033   ow_->StartObject("")
1034       ->StartObject("publisher")
1035       ->EndObject()
1036       ->RenderString("title", "My Title")
1037       ->EndObject();
1038   CheckOutput(expected);
1039 }
1040 
TEST_P(ProtoStreamObjectWriterTest,InvalidFieldValueAtRoot)1041 TEST_P(ProtoStreamObjectWriterTest, InvalidFieldValueAtRoot) {
1042   Book empty;
1043 
1044   EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_UINT32"),
1045                                       StringPiece("\"garbage\"")))
1046       .With(Args<0>(HasObjectLocation("length")));
1047   ow_->StartObject("")->RenderString("length", "garbage")->EndObject();
1048   CheckOutput(empty, 0);
1049 }
1050 
TEST_P(ProtoStreamObjectWriterTest,MultipleInvalidFieldValues)1051 TEST_P(ProtoStreamObjectWriterTest, MultipleInvalidFieldValues) {
1052   Book expected;
1053   expected.set_title("My Title");
1054 
1055   EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_UINT32"),
1056                                       StringPiece("\"-400\"")))
1057       .With(Args<0>(HasObjectLocation("length")));
1058   EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_INT64"),
1059                                       StringPiece("\"3.14\"")))
1060       .With(Args<0>(HasObjectLocation("published")));
1061   ow_->StartObject("")
1062       ->RenderString("length", "-400")
1063       ->RenderString("published", "3.14")
1064       ->RenderString("title", "My Title")
1065       ->EndObject();
1066   CheckOutput(expected);
1067 }
1068 
TEST_P(ProtoStreamObjectWriterTest,UnnamedFieldAtRoot)1069 TEST_P(ProtoStreamObjectWriterTest, UnnamedFieldAtRoot) {
1070   Book empty;
1071 
1072   EXPECT_CALL(listener_,
1073               InvalidName(_, StringPiece(""),
1074                           StringPiece("Proto fields must have a name.")))
1075       .With(Args<0>(HasObjectLocation("")));
1076   ow_->StartObject("")->RenderFloat("", 3.14)->EndObject();
1077   CheckOutput(empty, 0);
1078 }
1079 
TEST_P(ProtoStreamObjectWriterTest,UnnamedFieldAtAuthor)1080 TEST_P(ProtoStreamObjectWriterTest, UnnamedFieldAtAuthor) {
1081   Book expected;
1082   expected.set_title("noname");
1083   expected.set_allocated_author(new Author());
1084 
1085   EXPECT_CALL(listener_,
1086               InvalidName(_, StringPiece(""),
1087                           StringPiece("Proto fields must have a name.")))
1088       .With(Args<0>(HasObjectLocation("author")));
1089   ow_->StartObject("")
1090       ->StartObject("author")
1091       ->RenderInt32("", 123)
1092       ->EndObject()
1093       ->RenderString("title", "noname")
1094       ->EndObject();
1095   CheckOutput(expected);
1096 }
1097 
TEST_P(ProtoStreamObjectWriterTest,UnnamedListAtRoot)1098 TEST_P(ProtoStreamObjectWriterTest, UnnamedListAtRoot) {
1099   Book expected;
1100   expected.set_title("noname");
1101 
1102   EXPECT_CALL(listener_,
1103               InvalidName(_, StringPiece(""),
1104                           StringPiece("Proto fields must have a name.")))
1105       .With(Args<0>(HasObjectLocation("")));
1106   ow_->StartObject("")
1107       ->StartList("")
1108       ->EndList()
1109       ->RenderString("title", "noname")
1110       ->EndObject();
1111   CheckOutput(expected);
1112 }
1113 
TEST_P(ProtoStreamObjectWriterTest,RootNamedObject)1114 TEST_P(ProtoStreamObjectWriterTest, RootNamedObject) {
1115   Book expected;
1116   expected.set_title("Annie");
1117 
1118   EXPECT_CALL(
1119       listener_,
1120       InvalidName(_, StringPiece("oops"),
1121                   StringPiece("Root element should not be named.")))
1122       .With(Args<0>(HasObjectLocation("")));
1123   ow_->StartObject("oops")->RenderString("title", "Annie")->EndObject();
1124   CheckOutput(expected, 7);
1125 }
1126 
TEST_P(ProtoStreamObjectWriterTest,RootNamedList)1127 TEST_P(ProtoStreamObjectWriterTest, RootNamedList) {
1128   Book empty;
1129 
1130   EXPECT_CALL(
1131       listener_,
1132       InvalidName(_, StringPiece("oops"),
1133                   StringPiece("Root element should not be named.")))
1134       .With(Args<0>(HasObjectLocation("")));
1135   ow_->StartList("oops")->RenderString("", "item")->EndList();
1136   CheckOutput(empty, 0);
1137 }
1138 
TEST_P(ProtoStreamObjectWriterTest,RootUnnamedField)1139 TEST_P(ProtoStreamObjectWriterTest, RootUnnamedField) {
1140   Book empty;
1141 
1142   EXPECT_CALL(listener_,
1143               InvalidName(_, StringPiece(""),
1144                           StringPiece("Root element must be a message.")))
1145       .With(Args<0>(HasObjectLocation("")));
1146   ow_->RenderBool("", true);
1147   CheckOutput(empty, 0);
1148 }
1149 
TEST_P(ProtoStreamObjectWriterTest,RootNamedField)1150 TEST_P(ProtoStreamObjectWriterTest, RootNamedField) {
1151   Book empty;
1152 
1153   EXPECT_CALL(listener_,
1154               InvalidName(_, StringPiece("oops"),
1155                           StringPiece("Root element must be a message.")))
1156       .With(Args<0>(HasObjectLocation("")));
1157   ow_->RenderBool("oops", true);
1158   CheckOutput(empty, 0);
1159 }
1160 
TEST_P(ProtoStreamObjectWriterTest,NullValue)1161 TEST_P(ProtoStreamObjectWriterTest, NullValue) {
1162   Book empty;
1163 
1164   ow_->RenderNull("");
1165   CheckOutput(empty, 0);
1166 }
1167 
TEST_P(ProtoStreamObjectWriterTest,NullValueForMessageField)1168 TEST_P(ProtoStreamObjectWriterTest, NullValueForMessageField) {
1169   Book empty;
1170 
1171   ow_->RenderNull("author");
1172   CheckOutput(empty, 0);
1173 }
1174 
TEST_P(ProtoStreamObjectWriterTest,NullValueForPrimitiveField)1175 TEST_P(ProtoStreamObjectWriterTest, NullValueForPrimitiveField) {
1176   Book empty;
1177 
1178   ow_->RenderNull("length");
1179   CheckOutput(empty, 0);
1180 }
1181 
1182 class ProtoStreamObjectWriterTimestampDurationTest
1183     : public BaseProtoStreamObjectWriterTest {
1184  protected:
ProtoStreamObjectWriterTimestampDurationTest()1185   ProtoStreamObjectWriterTimestampDurationTest() {
1186     std::vector<const Descriptor*> descriptors;
1187     descriptors.push_back(TimestampDuration::descriptor());
1188     descriptors.push_back(google::protobuf::Timestamp::descriptor());
1189     descriptors.push_back(google::protobuf::Duration::descriptor());
1190     ResetTypeInfo(descriptors);
1191   }
1192 };
1193 
1194 INSTANTIATE_TEST_SUITE_P(DifferentTypeInfoSourceTest,
1195                          ProtoStreamObjectWriterTimestampDurationTest,
1196                          ::testing::Values(
1197                              testing::USE_TYPE_RESOLVER));
1198 
TEST_P(ProtoStreamObjectWriterTimestampDurationTest,ParseTimestamp)1199 TEST_P(ProtoStreamObjectWriterTimestampDurationTest, ParseTimestamp) {
1200   TimestampDuration timestamp;
1201   google::protobuf::Timestamp* ts = timestamp.mutable_ts();
1202   ts->set_seconds(1448249855);
1203   ts->set_nanos(33155000);
1204 
1205   ow_->StartObject("")
1206       ->RenderString("ts", "2015-11-23T03:37:35.033155Z")
1207       ->EndObject();
1208   CheckOutput(timestamp);
1209 }
1210 
TEST_P(ProtoStreamObjectWriterTimestampDurationTest,ParseTimestampYearNotZeroPadded)1211 TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
1212        ParseTimestampYearNotZeroPadded) {
1213   TimestampDuration timestamp;
1214   google::protobuf::Timestamp* ts = timestamp.mutable_ts();
1215   ts->set_seconds(-61665654145);
1216   ts->set_nanos(33155000);
1217 
1218   ow_->StartObject("")
1219       ->RenderString("ts", "15-11-23T03:37:35.033155Z")
1220       ->EndObject();
1221   CheckOutput(timestamp);
1222 }
1223 
TEST_P(ProtoStreamObjectWriterTimestampDurationTest,ParseTimestampYearZeroPadded)1224 TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
1225        ParseTimestampYearZeroPadded) {
1226   TimestampDuration timestamp;
1227   google::protobuf::Timestamp* ts = timestamp.mutable_ts();
1228   ts->set_seconds(-61665654145);
1229   ts->set_nanos(33155000);
1230 
1231   ow_->StartObject("")
1232       ->RenderString("ts", "0015-11-23T03:37:35.033155Z")
1233       ->EndObject();
1234   CheckOutput(timestamp);
1235 }
1236 
TEST_P(ProtoStreamObjectWriterTimestampDurationTest,ParseTimestampWithPositiveOffset)1237 TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
1238        ParseTimestampWithPositiveOffset) {
1239   TimestampDuration timestamp;
1240   google::protobuf::Timestamp* ts = timestamp.mutable_ts();
1241   ts->set_seconds(1448249855);
1242   ts->set_nanos(33155000);
1243 
1244   ow_->StartObject("")
1245       ->RenderString("ts", "2015-11-23T11:47:35.033155+08:10")
1246       ->EndObject();
1247   CheckOutput(timestamp);
1248 }
1249 
TEST_P(ProtoStreamObjectWriterTimestampDurationTest,ParseTimestampWithNegativeOffset)1250 TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
1251        ParseTimestampWithNegativeOffset) {
1252   TimestampDuration timestamp;
1253   google::protobuf::Timestamp* ts = timestamp.mutable_ts();
1254   ts->set_seconds(1448249855);
1255   ts->set_nanos(33155000);
1256 
1257   ow_->StartObject("")
1258       ->RenderString("ts", "2015-11-22T19:47:35.033155-07:50")
1259       ->EndObject();
1260   CheckOutput(timestamp);
1261 }
1262 
TEST_P(ProtoStreamObjectWriterTimestampDurationTest,TimestampWithInvalidOffset1)1263 TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
1264        TimestampWithInvalidOffset1) {
1265   TimestampDuration timestamp;
1266 
1267   EXPECT_CALL(
1268       listener_,
1269       InvalidValue(
1270           _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
1271           StringPiece("Field 'ts', Invalid time format: "
1272                       "2016-03-07T15:14:23+")));
1273 
1274   ow_->StartObject("")->RenderString("ts", "2016-03-07T15:14:23+")->EndObject();
1275   CheckOutput(timestamp);
1276 }
1277 
TEST_P(ProtoStreamObjectWriterTimestampDurationTest,TimestampWithInvalidOffset2)1278 TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
1279        TimestampWithInvalidOffset2) {
1280   TimestampDuration timestamp;
1281 
1282   EXPECT_CALL(
1283       listener_,
1284       InvalidValue(
1285           _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
1286           StringPiece("Field 'ts', Invalid time format: "
1287                       "2016-03-07T15:14:23+08-10")));
1288 
1289   ow_->StartObject("")
1290       ->RenderString("ts", "2016-03-07T15:14:23+08-10")
1291       ->EndObject();
1292   CheckOutput(timestamp);
1293 }
1294 
TEST_P(ProtoStreamObjectWriterTimestampDurationTest,TimestampWithInvalidOffset3)1295 TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
1296        TimestampWithInvalidOffset3) {
1297   TimestampDuration timestamp;
1298 
1299   EXPECT_CALL(
1300       listener_,
1301       InvalidValue(
1302           _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
1303           StringPiece("Field 'ts', Invalid time format: "
1304                       "2016-03-07T15:14:23+24:10")));
1305 
1306   ow_->StartObject("")
1307       ->RenderString("ts", "2016-03-07T15:14:23+24:10")
1308       ->EndObject();
1309   CheckOutput(timestamp);
1310 }
1311 
TEST_P(ProtoStreamObjectWriterTimestampDurationTest,TimestampWithInvalidOffset4)1312 TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
1313        TimestampWithInvalidOffset4) {
1314   TimestampDuration timestamp;
1315 
1316   EXPECT_CALL(
1317       listener_,
1318       InvalidValue(
1319           _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
1320           StringPiece("Field 'ts', Invalid time format: "
1321                       "2016-03-07T15:14:23+04:60")));
1322 
1323   ow_->StartObject("")
1324       ->RenderString("ts", "2016-03-07T15:14:23+04:60")
1325       ->EndObject();
1326   CheckOutput(timestamp);
1327 }
1328 
TEST_P(ProtoStreamObjectWriterTimestampDurationTest,InvalidTimestampError1)1329 TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError1) {
1330   TimestampDuration timestamp;
1331 
1332   EXPECT_CALL(
1333       listener_,
1334       InvalidValue(
1335           _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
1336           StringPiece("Field 'ts', Invalid time format: ")));
1337 
1338   ow_->StartObject("")->RenderString("ts", "")->EndObject();
1339   CheckOutput(timestamp);
1340 }
1341 
TEST_P(ProtoStreamObjectWriterTimestampDurationTest,InvalidTimestampError2)1342 TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError2) {
1343   TimestampDuration timestamp;
1344 
1345   EXPECT_CALL(
1346       listener_,
1347       InvalidValue(
1348           _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
1349           StringPiece("Field 'ts', Invalid time format: Z")));
1350 
1351   ow_->StartObject("")->RenderString("ts", "Z")->EndObject();
1352   CheckOutput(timestamp);
1353 }
1354 
TEST_P(ProtoStreamObjectWriterTimestampDurationTest,InvalidTimestampError3)1355 TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError3) {
1356   TimestampDuration timestamp;
1357 
1358   EXPECT_CALL(
1359       listener_,
1360       InvalidValue(
1361           _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
1362           StringPiece("Field 'ts', Invalid time format: "
1363                       "1970-01-01T00:00:00.ABZ")));
1364 
1365   ow_->StartObject("")
1366       ->RenderString("ts", "1970-01-01T00:00:00.ABZ")
1367       ->EndObject();
1368   CheckOutput(timestamp);
1369 }
1370 
TEST_P(ProtoStreamObjectWriterTimestampDurationTest,InvalidTimestampError4)1371 TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError4) {
1372   TimestampDuration timestamp;
1373 
1374   EXPECT_CALL(
1375       listener_,
1376       InvalidValue(
1377           _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
1378           StringPiece("Field 'ts', Invalid time format: "
1379                       "-8031-10-18T00:00:00.000Z")));
1380 
1381   ow_->StartObject("")
1382       ->RenderString("ts", "-8031-10-18T00:00:00.000Z")
1383       ->EndObject();
1384   CheckOutput(timestamp);
1385 }
1386 
TEST_P(ProtoStreamObjectWriterTimestampDurationTest,InvalidTimestampError5)1387 TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError5) {
1388   TimestampDuration timestamp;
1389 
1390   EXPECT_CALL(
1391       listener_,
1392       InvalidValue(
1393           _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
1394           StringPiece("Field 'ts', Invalid time format: "
1395                       "2015-11-23T03:37:35.033155   Z")));
1396 
1397   ow_->StartObject("")
1398       // Whitespace in the Timestamp nanos is not allowed.
1399       ->RenderString("ts", "2015-11-23T03:37:35.033155   Z")
1400       ->EndObject();
1401   CheckOutput(timestamp);
1402 }
1403 
TEST_P(ProtoStreamObjectWriterTimestampDurationTest,InvalidTimestampError6)1404 TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError6) {
1405   TimestampDuration timestamp;
1406 
1407   EXPECT_CALL(
1408       listener_,
1409       InvalidValue(
1410           _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
1411           StringPiece("Field 'ts', Invalid time format: "
1412                       "2015-11-23T03:37:35.033155 1234Z")));
1413 
1414   ow_->StartObject("")
1415       // Whitespace in the Timestamp nanos is not allowed.
1416       ->RenderString("ts", "2015-11-23T03:37:35.033155 1234Z")
1417       ->EndObject();
1418   CheckOutput(timestamp);
1419 }
1420 
TEST_P(ProtoStreamObjectWriterTimestampDurationTest,InvalidTimestampError7)1421 TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError7) {
1422   TimestampDuration timestamp;
1423 
1424   EXPECT_CALL(
1425       listener_,
1426       InvalidValue(
1427           _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
1428           StringPiece("Field 'ts', Invalid time format: "
1429                       "2015-11-23T03:37:35.033abc155Z")));
1430 
1431   ow_->StartObject("")
1432       // Non-numeric characters in the Timestamp nanos is not allowed.
1433       ->RenderString("ts", "2015-11-23T03:37:35.033abc155Z")
1434       ->EndObject();
1435   CheckOutput(timestamp);
1436 }
1437 
TEST_P(ProtoStreamObjectWriterTimestampDurationTest,InvalidTimestampError8)1438 TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError8) {
1439   TimestampDuration timestamp;
1440 
1441   EXPECT_CALL(
1442       listener_,
1443       InvalidValue(
1444           _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
1445           StringPiece("Field 'ts', Invalid time format: "
1446                       "0-12-31T23:59:59.000Z")));
1447 
1448   ow_->StartObject("")
1449       ->RenderString("ts", "0-12-31T23:59:59.000Z")
1450       ->EndObject();
1451   CheckOutput(timestamp);
1452 }
1453 
TEST_P(ProtoStreamObjectWriterTimestampDurationTest,ParseDuration)1454 TEST_P(ProtoStreamObjectWriterTimestampDurationTest, ParseDuration) {
1455   TimestampDuration duration;
1456   google::protobuf::Duration* dur = duration.mutable_dur();
1457   dur->set_seconds(1448216930);
1458   dur->set_nanos(132262000);
1459 
1460   ow_->StartObject("")->RenderString("dur", "1448216930.132262s")->EndObject();
1461   CheckOutput(duration);
1462 }
1463 
TEST_P(ProtoStreamObjectWriterTimestampDurationTest,InvalidDurationError1)1464 TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError1) {
1465   TimestampDuration duration;
1466 
1467   EXPECT_CALL(
1468       listener_,
1469       InvalidValue(
1470           _, StringPiece("type.googleapis.com/google.protobuf.Duration"),
1471           StringPiece(
1472               "Field 'dur', Illegal duration format; duration must "
1473               "end with 's'")));
1474 
1475   ow_->StartObject("")->RenderString("dur", "")->EndObject();
1476   CheckOutput(duration);
1477 }
1478 
TEST_P(ProtoStreamObjectWriterTimestampDurationTest,InvalidDurationError2)1479 TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError2) {
1480   TimestampDuration duration;
1481 
1482   EXPECT_CALL(
1483       listener_,
1484       InvalidValue(
1485           _, StringPiece("type.googleapis.com/google.protobuf.Duration"),
1486           StringPiece(
1487               "Field 'dur', Invalid duration format, failed to parse "
1488               "seconds")));
1489 
1490   ow_->StartObject("")->RenderString("dur", "s")->EndObject();
1491   CheckOutput(duration);
1492 }
1493 
TEST_P(ProtoStreamObjectWriterTimestampDurationTest,InvalidDurationError3)1494 TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError3) {
1495   TimestampDuration duration;
1496 
1497   EXPECT_CALL(
1498       listener_,
1499       InvalidValue(
1500           _, StringPiece("type.googleapis.com/google.protobuf.Duration"),
1501           StringPiece("Field 'dur', Invalid duration format, failed to "
1502                             "parse nano seconds")));
1503 
1504   ow_->StartObject("")->RenderString("dur", "123.DEFs")->EndObject();
1505   CheckOutput(duration);
1506 }
1507 
TEST_P(ProtoStreamObjectWriterTimestampDurationTest,InvalidDurationError4)1508 TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError4) {
1509   TimestampDuration duration;
1510 
1511   EXPECT_CALL(
1512       listener_,
1513       InvalidValue(
1514           _, StringPiece("type.googleapis.com/google.protobuf.Duration"),
1515           StringPiece("Field 'dur', Duration value exceeds limits")));
1516 
1517   ow_->StartObject("")->RenderString("dur", "315576000002s")->EndObject();
1518   CheckOutput(duration);
1519 }
1520 
TEST_P(ProtoStreamObjectWriterTimestampDurationTest,InvalidDurationError5)1521 TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError5) {
1522   TimestampDuration duration;
1523 
1524   EXPECT_CALL(
1525       listener_,
1526       InvalidValue(
1527           _, StringPiece("type.googleapis.com/google.protobuf.Duration"),
1528           StringPiece("Field 'dur', Duration value exceeds limits")));
1529 
1530   ow_->StartObject("")->RenderString("dur", "0.1000000001s")->EndObject();
1531   CheckOutput(duration);
1532 }
1533 
TEST_P(ProtoStreamObjectWriterTimestampDurationTest,MismatchedTimestampTypeInput)1534 TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
1535        MismatchedTimestampTypeInput) {
1536   TimestampDuration timestamp;
1537   EXPECT_CALL(
1538       listener_,
1539       InvalidValue(
1540           _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
1541           StringPiece(
1542               "Field 'ts', Invalid data type for timestamp, value is 1")))
1543       .With(Args<0>(HasObjectLocation("ts")));
1544   ow_->StartObject("")->RenderInt32("ts", 1)->EndObject();
1545   CheckOutput(timestamp);
1546 }
1547 
TEST_P(ProtoStreamObjectWriterTimestampDurationTest,MismatchedDurationTypeInput)1548 TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
1549        MismatchedDurationTypeInput) {
1550   TimestampDuration duration;
1551   EXPECT_CALL(
1552       listener_,
1553       InvalidValue(
1554           _, StringPiece("type.googleapis.com/google.protobuf.Duration"),
1555           StringPiece(
1556               "Field 'dur', Invalid data type for duration, value is 1")))
1557       .With(Args<0>(HasObjectLocation("dur")));
1558   ow_->StartObject("")->RenderInt32("dur", 1)->EndObject();
1559   CheckOutput(duration);
1560 }
1561 
TEST_P(ProtoStreamObjectWriterTimestampDurationTest,TimestampAcceptsNull)1562 TEST_P(ProtoStreamObjectWriterTimestampDurationTest, TimestampAcceptsNull) {
1563   TimestampDuration timestamp;
1564   EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0);
1565   ow_->StartObject("")->RenderNull("ts")->EndObject();
1566   CheckOutput(timestamp);
1567 }
1568 
TEST_P(ProtoStreamObjectWriterTimestampDurationTest,DurationAcceptsNull)1569 TEST_P(ProtoStreamObjectWriterTimestampDurationTest, DurationAcceptsNull) {
1570   TimestampDuration duration;
1571   EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0);
1572   ow_->StartObject("")->RenderNull("dur")->EndObject();
1573   CheckOutput(duration);
1574 }
1575 
1576 class ProtoStreamObjectWriterStructTest
1577     : public BaseProtoStreamObjectWriterTest {
1578  protected:
ProtoStreamObjectWriterStructTest()1579   ProtoStreamObjectWriterStructTest() { ResetProtoWriter(); }
1580 
1581   // Resets ProtoWriter with current set of options and other state.
ResetProtoWriter()1582   void ResetProtoWriter() {
1583     std::vector<const Descriptor*> descriptors;
1584     descriptors.push_back(StructType::descriptor());
1585     descriptors.push_back(google::protobuf::Struct::descriptor());
1586     ResetTypeInfo(descriptors);
1587   }
1588 };
1589 
1590 INSTANTIATE_TEST_SUITE_P(DifferentTypeInfoSourceTest,
1591                          ProtoStreamObjectWriterStructTest,
1592                          ::testing::Values(
1593                              testing::USE_TYPE_RESOLVER));
1594 
1595 // TODO(skarvaje): Write tests for failure cases.
TEST_P(ProtoStreamObjectWriterStructTest,StructRenderSuccess)1596 TEST_P(ProtoStreamObjectWriterStructTest, StructRenderSuccess) {
1597   StructType struct_type;
1598   google::protobuf::Struct* s = struct_type.mutable_object();
1599   s->mutable_fields()->operator[]("k1").set_number_value(123);
1600   s->mutable_fields()->operator[]("k2").set_bool_value(true);
1601 
1602   ow_->StartObject("")
1603       ->StartObject("object")
1604       ->RenderDouble("k1", 123)
1605       ->RenderBool("k2", true)
1606       ->EndObject()
1607       ->EndObject();
1608   CheckOutput(struct_type);
1609 }
1610 
TEST_P(ProtoStreamObjectWriterStructTest,StructNullInputSuccess)1611 TEST_P(ProtoStreamObjectWriterStructTest, StructNullInputSuccess) {
1612   StructType struct_type;
1613   EXPECT_CALL(listener_,
1614               InvalidName(_, StringPiece(""),
1615                           StringPiece("Proto fields must have a name.")))
1616       .With(Args<0>(HasObjectLocation("")));
1617   ow_->StartObject("")->RenderNull("")->EndObject();
1618   CheckOutput(struct_type);
1619 }
1620 
TEST_P(ProtoStreamObjectWriterStructTest,StructInvalidInputFailure)1621 TEST_P(ProtoStreamObjectWriterStructTest, StructInvalidInputFailure) {
1622   StructType struct_type;
1623   EXPECT_CALL(
1624       listener_,
1625       InvalidValue(
1626           _, StringPiece("type.googleapis.com/google.protobuf.Struct"),
1627           StringPiece("true")))
1628       .With(Args<0>(HasObjectLocation("object")));
1629 
1630   ow_->StartObject("")->RenderBool("object", true)->EndObject();
1631   CheckOutput(struct_type);
1632 }
1633 
TEST_P(ProtoStreamObjectWriterStructTest,StructAcceptsNull)1634 TEST_P(ProtoStreamObjectWriterStructTest, StructAcceptsNull) {
1635   StructType struct_type;
1636   EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0);
1637 
1638   ow_->StartObject("")->RenderNull("object")->EndObject();
1639   CheckOutput(struct_type);
1640 }
1641 
TEST_P(ProtoStreamObjectWriterStructTest,StructValuePreservesNull)1642 TEST_P(ProtoStreamObjectWriterStructTest, StructValuePreservesNull) {
1643   StructType struct_type;
1644   (*struct_type.mutable_object()->mutable_fields())["key"].set_null_value(
1645       google::protobuf::NULL_VALUE);
1646   EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0);
1647 
1648   ow_->StartObject("")
1649       ->StartObject("object")
1650       ->RenderNull("key")
1651       ->EndObject()
1652       ->EndObject();
1653   CheckOutput(struct_type);
1654 }
1655 
TEST_P(ProtoStreamObjectWriterStructTest,SimpleRepeatedStructMapKeyTest)1656 TEST_P(ProtoStreamObjectWriterStructTest, SimpleRepeatedStructMapKeyTest) {
1657   EXPECT_CALL(listener_,
1658               InvalidName(_, StringPiece("gBike"),
1659                           StringPiece(
1660                               "Repeated map key: 'gBike' is already set.")));
1661   ow_->StartObject("")
1662       ->StartObject("object")
1663       ->RenderString("gBike", "v1")
1664       ->RenderString("gBike", "v2")
1665       ->EndObject()
1666       ->EndObject();
1667 }
1668 
TEST_P(ProtoStreamObjectWriterStructTest,RepeatedStructMapListKeyTest)1669 TEST_P(ProtoStreamObjectWriterStructTest, RepeatedStructMapListKeyTest) {
1670   EXPECT_CALL(
1671       listener_,
1672       InvalidName(_, StringPiece("k1"),
1673                   StringPiece("Repeated map key: 'k1' is already set.")));
1674   ow_->StartObject("")
1675       ->StartObject("object")
1676       ->RenderString("k1", "v1")
1677       ->StartList("k1")
1678       ->RenderString("", "v2")
1679       ->EndList()
1680       ->EndObject()
1681       ->EndObject();
1682 }
1683 
TEST_P(ProtoStreamObjectWriterStructTest,RepeatedStructMapObjectKeyTest)1684 TEST_P(ProtoStreamObjectWriterStructTest, RepeatedStructMapObjectKeyTest) {
1685   EXPECT_CALL(
1686       listener_,
1687       InvalidName(_, StringPiece("k1"),
1688                   StringPiece("Repeated map key: 'k1' is already set.")));
1689   ow_->StartObject("")
1690       ->StartObject("object")
1691       ->StartObject("k1")
1692       ->RenderString("sub_k1", "v1")
1693       ->EndObject()
1694       ->StartObject("k1")
1695       ->RenderString("sub_k2", "v2")
1696       ->EndObject()
1697       ->EndObject()
1698       ->EndObject();
1699 }
1700 
TEST_P(ProtoStreamObjectWriterStructTest,OptionStructIntAsStringsTest)1701 TEST_P(ProtoStreamObjectWriterStructTest, OptionStructIntAsStringsTest) {
1702   StructType struct_type;
1703   google::protobuf::Struct* s = struct_type.mutable_object();
1704   s->mutable_fields()->operator[]("k1").set_string_value("123");
1705   s->mutable_fields()->operator[]("k2").set_bool_value(true);
1706   s->mutable_fields()->operator[]("k3").set_string_value("-222222222");
1707   s->mutable_fields()->operator[]("k4").set_string_value("33333333");
1708 
1709   options_.struct_integers_as_strings = true;
1710   ResetProtoWriter();
1711 
1712   ow_->StartObject("")
1713       ->StartObject("object")
1714       ->RenderDouble("k1", 123)
1715       ->RenderBool("k2", true)
1716       ->RenderInt64("k3", -222222222)
1717       ->RenderUint64("k4", 33333333)
1718       ->EndObject()
1719       ->EndObject();
1720   CheckOutput(struct_type);
1721 }
1722 
TEST_P(ProtoStreamObjectWriterStructTest,Struct32BitIntsAndFloatsTest)1723 TEST_P(ProtoStreamObjectWriterStructTest, Struct32BitIntsAndFloatsTest) {
1724   StructType struct_type;
1725   google::protobuf::Struct* s = struct_type.mutable_object();
1726   s->mutable_fields()->operator[]("k1").set_number_value(1.5);
1727   s->mutable_fields()->operator[]("k2").set_number_value(100);
1728   s->mutable_fields()->operator[]("k3").set_number_value(100);
1729   ResetProtoWriter();
1730 
1731   ow_->StartObject("")
1732       ->StartObject("object")
1733       ->RenderFloat("k1", 1.5)
1734       ->RenderInt32("k2", 100)
1735       ->RenderUint32("k3", 100)
1736       ->EndObject()
1737       ->EndObject();
1738   CheckOutput(struct_type);
1739 }
1740 
TEST_P(ProtoStreamObjectWriterStructTest,Struct32BitIntsAndFloatsAsStringsTest)1741 TEST_P(ProtoStreamObjectWriterStructTest,
1742        Struct32BitIntsAndFloatsAsStringsTest) {
1743   StructType struct_type;
1744   google::protobuf::Struct* s = struct_type.mutable_object();
1745   s->mutable_fields()->operator[]("k1").set_string_value("1.5");
1746   s->mutable_fields()->operator[]("k2").set_string_value("100");
1747   s->mutable_fields()->operator[]("k3").set_string_value("100");
1748 
1749   options_.struct_integers_as_strings = true;
1750   ResetProtoWriter();
1751 
1752   ow_->StartObject("")
1753       ->StartObject("object")
1754       ->RenderFloat("k1", 1.5)
1755       ->RenderInt32("k2", 100)
1756       ->RenderUint32("k3", 100)
1757       ->EndObject()
1758       ->EndObject();
1759   CheckOutput(struct_type);
1760 }
1761 
TEST_P(ProtoStreamObjectWriterStructTest,ValuePreservesNull)1762 TEST_P(ProtoStreamObjectWriterStructTest, ValuePreservesNull) {
1763   ValueWrapper value;
1764   value.mutable_value()->set_null_value(google::protobuf::NULL_VALUE);
1765 
1766   EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0);
1767   ow_->StartObject("")->RenderNull("value")->EndObject();
1768   CheckOutput(value);
1769 }
1770 
1771 class ProtoStreamObjectWriterMapTest : public BaseProtoStreamObjectWriterTest {
1772  protected:
ProtoStreamObjectWriterMapTest()1773   ProtoStreamObjectWriterMapTest() {
1774     std::vector<const Descriptor*> descriptors;
1775     descriptors.push_back(MapIn::descriptor());
1776     descriptors.push_back(google::protobuf::DoubleValue::descriptor());
1777     ResetTypeInfo(descriptors);
1778   }
1779 };
1780 
1781 INSTANTIATE_TEST_SUITE_P(DifferentTypeInfoSourceTest,
1782                          ProtoStreamObjectWriterMapTest,
1783                          ::testing::Values(
1784                              testing::USE_TYPE_RESOLVER));
1785 
TEST_P(ProtoStreamObjectWriterMapTest,MapShouldNotAcceptList)1786 TEST_P(ProtoStreamObjectWriterMapTest, MapShouldNotAcceptList) {
1787   MapIn mm;
1788   EXPECT_CALL(
1789       listener_,
1790       InvalidValue(_, StringPiece("Map"),
1791                    StringPiece(
1792                        "Cannot bind a list to map for field 'map_input'.")));
1793   ow_->StartObject("")
1794       ->StartList("map_input")
1795       ->RenderString("a", "b")
1796       ->EndList()
1797       ->EndObject();
1798   CheckOutput(mm);
1799 }
1800 
TEST_P(ProtoStreamObjectWriterMapTest,MapAcceptsNullValue)1801 TEST_P(ProtoStreamObjectWriterMapTest, MapAcceptsNullValue) {
1802   // Null should not be a valid map value.
1803   // See http://go/proto3-json-spec#heading=h.r2ddatp7y4vi
1804   // This test is added for backward compatibility.
1805   MapIn mm;
1806   (*mm.mutable_map_input())["a"] = "b";
1807   (*mm.mutable_map_input())["x"] = "";
1808   ow_->StartObject("")
1809       ->StartObject("map_input")
1810       ->RenderString("a", "b")
1811       ->RenderNull("x")
1812       ->EndObject()
1813       ->EndObject();
1814   CheckOutput(mm);
1815 }
1816 
TEST_P(ProtoStreamObjectWriterMapTest,MapShouldIgnoreNullValueEntry)1817 TEST_P(ProtoStreamObjectWriterMapTest, MapShouldIgnoreNullValueEntry) {
1818   options_.ignore_null_value_map_entry = true;
1819   ResetTypeInfo(MapIn::descriptor());
1820   MapIn mm;
1821   (*mm.mutable_map_input())["a"] = "b";
1822   ow_->StartObject("")
1823       ->StartObject("map_input")
1824       ->RenderString("a", "b")
1825       ->RenderNull("x")
1826       ->EndObject()
1827       ->EndObject();
1828   CheckOutput(mm);
1829 }
1830 
TEST_P(ProtoStreamObjectWriterMapTest,RepeatedMapKeyTest)1831 TEST_P(ProtoStreamObjectWriterMapTest, RepeatedMapKeyTest) {
1832   EXPECT_CALL(
1833       listener_,
1834       InvalidName(_, StringPiece("k1"),
1835                   StringPiece("Repeated map key: 'k1' is already set.")));
1836   ow_->StartObject("")
1837       ->RenderString("other", "test")
1838       ->StartObject("map_input")
1839       ->RenderString("k1", "v1")
1840       ->RenderString("k1", "v2")
1841       ->EndObject()
1842       ->EndObject();
1843 }
1844 
TEST_P(ProtoStreamObjectWriterMapTest,AnyInMap)1845 TEST_P(ProtoStreamObjectWriterMapTest, AnyInMap) {
1846   MapIn mm;
1847   google::protobuf::DoubleValue d;
1848   d.set_value(40.2);
1849   (*mm.mutable_map_any())["foo"].PackFrom(d);
1850   ow_->StartObject("")
1851       ->StartObject("map_any")
1852       ->StartObject("foo")
1853       ->RenderString("@type", "type.googleapis.com/google.protobuf.DoubleValue")
1854       ->RenderDouble("value", 40.2)
1855       ->EndObject()
1856       ->EndObject()
1857       ->EndObject();
1858   CheckOutput(mm);
1859 }
1860 
1861 class ProtoStreamObjectWriterAnyTest : public BaseProtoStreamObjectWriterTest {
1862  protected:
ProtoStreamObjectWriterAnyTest()1863   ProtoStreamObjectWriterAnyTest() {
1864     std::vector<const Descriptor*> descriptors;
1865     descriptors.push_back(AnyOut::descriptor());
1866     descriptors.push_back(Book::descriptor());
1867     descriptors.push_back(google::protobuf::Any::descriptor());
1868     descriptors.push_back(google::protobuf::DoubleValue::descriptor());
1869     descriptors.push_back(google::protobuf::FieldMask::descriptor());
1870     descriptors.push_back(google::protobuf::Int32Value::descriptor());
1871     descriptors.push_back(google::protobuf::Struct::descriptor());
1872     descriptors.push_back(google::protobuf::Timestamp::descriptor());
1873     descriptors.push_back(google::protobuf::Value::descriptor());
1874     ResetTypeInfo(descriptors);
1875   }
1876 };
1877 
1878 INSTANTIATE_TEST_SUITE_P(DifferentTypeInfoSourceTest,
1879                          ProtoStreamObjectWriterAnyTest,
1880                          ::testing::Values(
1881                              testing::USE_TYPE_RESOLVER));
1882 
TEST_P(ProtoStreamObjectWriterAnyTest,AnyRenderSuccess)1883 TEST_P(ProtoStreamObjectWriterAnyTest, AnyRenderSuccess) {
1884   AnyOut any;
1885   google::protobuf::Any* any_type = any.mutable_any();
1886   any_type->set_type_url("type.googleapis.com/google.protobuf.DoubleValue");
1887   google::protobuf::DoubleValue d;
1888   d.set_value(40.2);
1889   any_type->set_value(d.SerializeAsString());
1890 
1891   ow_->StartObject("")
1892       ->StartObject("any")
1893       ->RenderString("@type", "type.googleapis.com/google.protobuf.DoubleValue")
1894       ->RenderDouble("value", 40.2)
1895       ->EndObject()
1896       ->EndObject();
1897   CheckOutput(any);
1898 }
1899 
TEST_P(ProtoStreamObjectWriterAnyTest,RecursiveAny)1900 TEST_P(ProtoStreamObjectWriterAnyTest, RecursiveAny) {
1901   AnyOut out;
1902   ::google::protobuf::Any* any = out.mutable_any();
1903   any->set_type_url("type.googleapis.com/google.protobuf.Any");
1904 
1905   ::google::protobuf::Any nested_any;
1906   nested_any.set_type_url(
1907       "type.googleapis.com/proto_util_converter.testing.AnyM");
1908 
1909   AnyM m;
1910   m.set_foo("foovalue");
1911   nested_any.set_value(m.SerializeAsString());
1912 
1913   any->set_value(nested_any.SerializeAsString());
1914 
1915   ow_->StartObject("")
1916       ->StartObject("any")
1917       ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
1918       ->StartObject("value")
1919       ->RenderString("@type",
1920                      "type.googleapis.com/proto_util_converter.testing.AnyM")
1921       ->RenderString("foo", "foovalue")
1922       ->EndObject()
1923       ->EndObject()
1924       ->EndObject();
1925   CheckOutput(out, 112);
1926 }
1927 
TEST_P(ProtoStreamObjectWriterAnyTest,DoubleRecursiveAny)1928 TEST_P(ProtoStreamObjectWriterAnyTest, DoubleRecursiveAny) {
1929   AnyOut out;
1930   ::google::protobuf::Any* any = out.mutable_any();
1931   any->set_type_url("type.googleapis.com/google.protobuf.Any");
1932 
1933   ::google::protobuf::Any nested_any;
1934   nested_any.set_type_url("type.googleapis.com/google.protobuf.Any");
1935 
1936   ::google::protobuf::Any second_nested_any;
1937   second_nested_any.set_type_url(
1938       "type.googleapis.com/proto_util_converter.testing.AnyM");
1939 
1940   AnyM m;
1941   m.set_foo("foovalue");
1942   second_nested_any.set_value(m.SerializeAsString());
1943 
1944   nested_any.set_value(second_nested_any.SerializeAsString());
1945   any->set_value(nested_any.SerializeAsString());
1946 
1947   ow_->StartObject("")
1948       ->StartObject("any")
1949       ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
1950       ->StartObject("value")
1951       ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
1952       ->StartObject("value")
1953       ->RenderString("@type",
1954                      "type.googleapis.com/proto_util_converter.testing.AnyM")
1955       ->RenderString("foo", "foovalue")
1956       ->EndObject()
1957       ->EndObject()
1958       ->EndObject()
1959       ->EndObject();
1960   CheckOutput(out, 156);
1961 }
1962 
TEST_P(ProtoStreamObjectWriterAnyTest,TypeUrlAtEnd)1963 TEST_P(ProtoStreamObjectWriterAnyTest, TypeUrlAtEnd) {
1964   Book book;
1965   book.set_title("C++");
1966   book.set_length(1234);
1967   book.set_content("Hello World!");
1968 
1969   ::google::protobuf::Any any;
1970   any.PackFrom(book);
1971 
1972   ::google::protobuf::Any outer_any;
1973   outer_any.PackFrom(any);
1974 
1975   AnyOut out;
1976   out.mutable_any()->PackFrom(outer_any);
1977 
1978   // Put the @type field at the end of each Any message. Parsers should
1979   // be able to accept that.
1980   ow_->StartObject("")
1981       ->StartObject("any")
1982       ->StartObject("value")
1983       ->StartObject("value")
1984       ->RenderString("title", "C++")
1985       ->RenderInt32("length", 1234)
1986       ->RenderBytes("content", "Hello World!")
1987       ->RenderString("@type",
1988                      "type.googleapis.com/proto_util_converter.testing.Book")
1989       ->EndObject()
1990       ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
1991       ->EndObject()
1992       ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
1993       ->EndObject()
1994       ->EndObject();
1995   CheckOutput(out);
1996 }
1997 
1998 // Same as TypeUrlAtEnd, but use temporary string values to make sure we don't
1999 // mistakenly store StringPiece objects pointing to invalid memory.
TEST_P(ProtoStreamObjectWriterAnyTest,TypeUrlAtEndWithTemporaryStrings)2000 TEST_P(ProtoStreamObjectWriterAnyTest, TypeUrlAtEndWithTemporaryStrings) {
2001   Book book;
2002   book.set_title("C++");
2003   book.set_length(1234);
2004   book.set_content("Hello World!");
2005 
2006   ::google::protobuf::Any any;
2007   any.PackFrom(book);
2008 
2009   ::google::protobuf::Any outer_any;
2010   outer_any.PackFrom(any);
2011 
2012   AnyOut out;
2013   out.mutable_any()->PackFrom(outer_any);
2014 
2015   std::string name, value;
2016   // Put the @type field at the end of each Any message. Parsers should
2017   // be able to accept that.
2018   ow_->StartObject("")->StartObject("any");
2019   {
2020     ow_->StartObject("value");
2021     {
2022       ow_->StartObject("value");
2023       {
2024         name = "title";
2025         value = "C++";
2026         ow_->RenderString(name, value);
2027         name = "length";
2028         ow_->RenderInt32(name, 1234);
2029         name = "content";
2030         value = "Hello World!";
2031         ow_->RenderBytes(name, value);
2032         name = "@type";
2033         value = "type.googleapis.com/proto_util_converter.testing.Book";
2034         ow_->RenderString(name, value);
2035       }
2036       ow_->EndObject();
2037 
2038       name = "@type";
2039       value = "type.googleapis.com/google.protobuf.Any";
2040       ow_->RenderString(name, value);
2041     }
2042     ow_->EndObject();
2043 
2044     name = "@type";
2045     value = "type.googleapis.com/google.protobuf.Any";
2046     ow_->RenderString(name, value);
2047   }
2048   ow_->EndObject()->EndObject();
2049   CheckOutput(out);
2050 }
2051 
TEST_P(ProtoStreamObjectWriterAnyTest,EmptyAnyFromEmptyObject)2052 TEST_P(ProtoStreamObjectWriterAnyTest, EmptyAnyFromEmptyObject) {
2053   AnyOut out;
2054   out.mutable_any();
2055 
2056   EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0);
2057 
2058   ow_->StartObject("")->StartObject("any")->EndObject()->EndObject();
2059 
2060   CheckOutput(out, 2);
2061 }
2062 
TEST_P(ProtoStreamObjectWriterAnyTest,AnyWithoutTypeUrlFails1)2063 TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails1) {
2064   AnyOut any;
2065 
2066   EXPECT_CALL(
2067       listener_,
2068       InvalidValue(_, StringPiece("Any"),
2069                    StringPiece("Missing @type for any field in "
2070                                      "proto_util_converter.testing.AnyOut")));
2071 
2072   ow_->StartObject("")
2073       ->StartObject("any")
2074       ->StartObject("another")
2075       ->EndObject()
2076       ->EndObject()
2077       ->EndObject();
2078   CheckOutput(any);
2079 }
2080 
TEST_P(ProtoStreamObjectWriterAnyTest,AnyWithoutTypeUrlFails2)2081 TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails2) {
2082   AnyOut any;
2083 
2084   EXPECT_CALL(
2085       listener_,
2086       InvalidValue(_, StringPiece("Any"),
2087                    StringPiece("Missing @type for any field in "
2088                                      "proto_util_converter.testing.AnyOut")));
2089 
2090   ow_->StartObject("")
2091       ->StartObject("any")
2092       ->StartList("another")
2093       ->EndObject()
2094       ->EndObject()
2095       ->EndObject();
2096   CheckOutput(any);
2097 }
2098 
TEST_P(ProtoStreamObjectWriterAnyTest,AnyWithoutTypeUrlFails3)2099 TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails3) {
2100   AnyOut any;
2101 
2102   EXPECT_CALL(
2103       listener_,
2104       InvalidValue(_, StringPiece("Any"),
2105                    StringPiece("Missing @type for any field in "
2106                                      "proto_util_converter.testing.AnyOut")));
2107 
2108   ow_->StartObject("")
2109       ->StartObject("any")
2110       ->RenderString("value", "somevalue")
2111       ->EndObject()
2112       ->EndObject();
2113   CheckOutput(any);
2114 }
2115 
TEST_P(ProtoStreamObjectWriterAnyTest,AnyWithInvalidTypeUrlFails)2116 TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithInvalidTypeUrlFails) {
2117   AnyOut any;
2118 
2119   EXPECT_CALL(
2120       listener_,
2121       InvalidValue(
2122           _, StringPiece("Any"),
2123           StringPiece("Invalid type URL, type URLs must be of the form "
2124                             "'type.googleapis.com/<typename>', got: "
2125                             "type.other.com/some.Type")));
2126 
2127   ow_->StartObject("")
2128       ->StartObject("any")
2129       ->RenderString("@type", "type.other.com/some.Type")
2130       ->RenderDouble("value", 40.2)
2131       ->EndObject()
2132       ->EndObject();
2133   CheckOutput(any);
2134 }
2135 
TEST_P(ProtoStreamObjectWriterAnyTest,AnyWithUnknownTypeFails)2136 TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithUnknownTypeFails) {
2137   AnyOut any;
2138 
2139   EXPECT_CALL(listener_,
2140               InvalidValue(_, StringPiece("Any"),
2141                            StringPiece(
2142                                "Invalid type URL, unknown type: some.Type")));
2143   ow_->StartObject("")
2144       ->StartObject("any")
2145       ->RenderString("@type", "type.googleapis.com/some.Type")
2146       ->RenderDouble("value", 40.2)
2147       ->EndObject()
2148       ->EndObject();
2149   CheckOutput(any);
2150 }
2151 
TEST_P(ProtoStreamObjectWriterAnyTest,AnyIncorrectInputTypeFails)2152 TEST_P(ProtoStreamObjectWriterAnyTest, AnyIncorrectInputTypeFails) {
2153   AnyOut any;
2154 
2155   EXPECT_CALL(
2156       listener_,
2157       InvalidValue(_,
2158                    StringPiece("type.googleapis.com/google.protobuf.Any"),
2159                    StringPiece("1")));
2160   ow_->StartObject("")->RenderInt32("any", 1)->EndObject();
2161   CheckOutput(any);
2162 }
2163 
TEST_P(ProtoStreamObjectWriterAnyTest,AnyAcceptsNull)2164 TEST_P(ProtoStreamObjectWriterAnyTest, AnyAcceptsNull) {
2165   AnyOut any;
2166 
2167   EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0);
2168   ow_->StartObject("")->RenderNull("any")->EndObject();
2169   CheckOutput(any);
2170 }
2171 
TEST_P(ProtoStreamObjectWriterAnyTest,AnyWellKnownTypeErrorTest)2172 TEST_P(ProtoStreamObjectWriterAnyTest, AnyWellKnownTypeErrorTest) {
2173   EXPECT_CALL(listener_, InvalidValue(_, StringPiece("Any"),
2174                                       StringPiece("Invalid time format: ")));
2175 
2176   AnyOut any;
2177   google::protobuf::Any* any_type = any.mutable_any();
2178   any_type->set_type_url("type.googleapis.com/google.protobuf.Timestamp");
2179 
2180   ow_->StartObject("")
2181       ->StartObject("any")
2182       ->RenderString("@type", "type.googleapis.com/google.protobuf.Timestamp")
2183       ->RenderString("value", "")
2184       ->EndObject()
2185       ->EndObject();
2186   CheckOutput(any);
2187 }
2188 
2189 // Test the following case:
2190 //
2191 // {
2192 //   "any": {
2193 //     "@type": "type.googleapis.com/google.protobuf.Value",
2194 //     "value": "abc"
2195 //   }
2196 // }
TEST_P(ProtoStreamObjectWriterAnyTest,AnyWithNestedPrimitiveValue)2197 TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithNestedPrimitiveValue) {
2198   AnyOut out;
2199   ::google::protobuf::Any* any = out.mutable_any();
2200 
2201   ::google::protobuf::Value value;
2202   value.set_string_value("abc");
2203   any->PackFrom(value);
2204 
2205   ow_->StartObject("")
2206       ->StartObject("any")
2207       ->RenderString("@type", "type.googleapis.com/google.protobuf.Value")
2208       ->RenderString("value", "abc")
2209       ->EndObject()
2210       ->EndObject();
2211   CheckOutput(out);
2212 }
2213 
2214 // Test the following case:
2215 //
2216 // {
2217 //   "any": {
2218 //     "@type": "type.googleapis.com/google.protobuf.Value",
2219 //     "value": {
2220 //       "foo": "abc"
2221 //     }
2222 //   }
2223 // }
TEST_P(ProtoStreamObjectWriterAnyTest,AnyWithNestedObjectValue)2224 TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithNestedObjectValue) {
2225   AnyOut out;
2226   ::google::protobuf::Any* any = out.mutable_any();
2227 
2228   ::google::protobuf::Value value;
2229   (*value.mutable_struct_value()->mutable_fields())["foo"].set_string_value(
2230       "abc");
2231   any->PackFrom(value);
2232 
2233   ow_->StartObject("")
2234       ->StartObject("any")
2235       ->RenderString("@type", "type.googleapis.com/google.protobuf.Value")
2236       ->StartObject("value")
2237       ->RenderString("foo", "abc")
2238       ->EndObject()
2239       ->EndObject()
2240       ->EndObject();
2241   CheckOutput(out);
2242 }
2243 
2244 // Test the following case:
2245 //
2246 // {
2247 //   "any": {
2248 //     "@type": "type.googleapis.com/google.protobuf.Value",
2249 //     "value": ["hello"],
2250 //   }
2251 // }
TEST_P(ProtoStreamObjectWriterAnyTest,AnyWithNestedArrayValue)2252 TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithNestedArrayValue) {
2253   AnyOut out;
2254   ::google::protobuf::Any* any = out.mutable_any();
2255 
2256   ::google::protobuf::Value value;
2257   value.mutable_list_value()->add_values()->set_string_value("hello");
2258   any->PackFrom(value);
2259 
2260   ow_->StartObject("")
2261       ->StartObject("any")
2262       ->RenderString("@type", "type.googleapis.com/google.protobuf.Value")
2263       ->StartList("value")
2264       ->RenderString("", "hello")
2265       ->EndList()
2266       ->EndObject()
2267       ->EndObject()
2268       ->EndObject();
2269   CheckOutput(out);
2270 }
2271 
2272 // Test the following case:
2273 //
2274 // {
2275 //   "any": {
2276 //     "@type": "type.googleapis.com/google.protobuf.Value",
2277 //     "not_value": ""
2278 //   }
2279 // }
TEST_P(ProtoStreamObjectWriterAnyTest,AnyWellKnownTypesNoValueFieldForPrimitive)2280 TEST_P(ProtoStreamObjectWriterAnyTest,
2281        AnyWellKnownTypesNoValueFieldForPrimitive) {
2282   EXPECT_CALL(
2283       listener_,
2284       InvalidValue(
2285           _, StringPiece("Any"),
2286           StringPiece("Expect a \"value\" field for well-known types.")));
2287   AnyOut any;
2288   google::protobuf::Any* any_type = any.mutable_any();
2289   any_type->set_type_url("type.googleapis.com/google.protobuf.Value");
2290 
2291   ow_->StartObject("")
2292       ->StartObject("any")
2293       ->RenderString("@type", "type.googleapis.com/google.protobuf.Value")
2294       ->RenderString("not_value", "")
2295       ->EndObject()
2296       ->EndObject();
2297   CheckOutput(any);
2298 }
2299 
2300 // Test the following case:
2301 //
2302 // {
2303 //   "any": {
2304 //     "@type": "type.googleapis.com/google.protobuf.Value",
2305 //     "not_value": {}
2306 //   }
2307 // }
TEST_P(ProtoStreamObjectWriterAnyTest,AnyWellKnownTypesNoValueFieldForObject)2308 TEST_P(ProtoStreamObjectWriterAnyTest, AnyWellKnownTypesNoValueFieldForObject) {
2309   EXPECT_CALL(
2310       listener_,
2311       InvalidValue(
2312           _, StringPiece("Any"),
2313           StringPiece("Expect a \"value\" field for well-known types.")));
2314   AnyOut any;
2315   google::protobuf::Any* any_type = any.mutable_any();
2316   any_type->set_type_url("type.googleapis.com/google.protobuf.Value");
2317 
2318   ow_->StartObject("")
2319       ->StartObject("any")
2320       ->RenderString("@type", "type.googleapis.com/google.protobuf.Value")
2321       ->StartObject("not_value")
2322       ->EndObject()
2323       ->EndObject()
2324       ->EndObject();
2325   CheckOutput(any);
2326 }
2327 
2328 // Test the following case:
2329 //
2330 // {
2331 //   "any": {
2332 //     "@type": "type.googleapis.com/google.protobuf.Value",
2333 //     "not_value": [],
2334 //   }
2335 // }
TEST_P(ProtoStreamObjectWriterAnyTest,AnyWellKnownTypesNoValueFieldForArray)2336 TEST_P(ProtoStreamObjectWriterAnyTest, AnyWellKnownTypesNoValueFieldForArray) {
2337   EXPECT_CALL(
2338       listener_,
2339       InvalidValue(
2340           _, StringPiece("Any"),
2341           StringPiece("Expect a \"value\" field for well-known types.")));
2342   AnyOut any;
2343   google::protobuf::Any* any_type = any.mutable_any();
2344   any_type->set_type_url("type.googleapis.com/google.protobuf.Value");
2345 
2346   ow_->StartObject("")
2347       ->StartObject("any")
2348       ->RenderString("@type", "type.googleapis.com/google.protobuf.Value")
2349       ->StartList("not_value")
2350       ->EndList()
2351       ->EndObject()
2352       ->EndObject()
2353       ->EndObject();
2354   CheckOutput(any);
2355 }
2356 
2357 // Test the following case:
2358 //
2359 // {
2360 //   "any": {
2361 //     "@type": "type.googleapis.com/google.protobuf.Struct",
2362 //     "value": "",
2363 //   }
2364 // }
TEST_P(ProtoStreamObjectWriterAnyTest,AnyWellKnownTypesExpectObjectForStruct)2365 TEST_P(ProtoStreamObjectWriterAnyTest, AnyWellKnownTypesExpectObjectForStruct) {
2366   EXPECT_CALL(listener_,
2367               InvalidValue(_, StringPiece("Any"),
2368                            StringPiece("Expect a JSON object.")));
2369   AnyOut any;
2370   google::protobuf::Any* any_type = any.mutable_any();
2371   any_type->set_type_url("type.googleapis.com/google.protobuf.Struct");
2372 
2373   ow_->StartObject("")
2374       ->StartObject("any")
2375       ->RenderString("@type", "type.googleapis.com/google.protobuf.Struct")
2376       ->RenderString("value", "")
2377       ->EndObject()
2378       ->EndObject();
2379   CheckOutput(any);
2380 }
2381 
2382 // Test the following case:
2383 //
2384 // {
2385 //   "any": {
2386 //     "@type": "type.googleapis.com/google.protobuf.Any",
2387 //     "value": "",
2388 //   }
2389 // }
TEST_P(ProtoStreamObjectWriterAnyTest,AnyWellKnownTypesExpectObjectForAny)2390 TEST_P(ProtoStreamObjectWriterAnyTest, AnyWellKnownTypesExpectObjectForAny) {
2391   EXPECT_CALL(listener_,
2392               InvalidValue(_, StringPiece("Any"),
2393                            StringPiece("Expect a JSON object.")));
2394   AnyOut any;
2395   google::protobuf::Any* any_type = any.mutable_any();
2396   any_type->set_type_url("type.googleapis.com/google.protobuf.Any");
2397 
2398   ow_->StartObject("")
2399       ->StartObject("any")
2400       ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
2401       ->RenderString("value", "")
2402       ->EndObject()
2403       ->EndObject();
2404   CheckOutput(any);
2405 }
2406 
2407 // {
2408 //   "any": {
2409 //     "@type": "type.googleapis.com/google.protobuf.Any",
2410 //     "value": null
2411 //   }
2412 // }
TEST_P(ProtoStreamObjectWriterAnyTest,AnyInAnyAcceptsNull)2413 TEST_P(ProtoStreamObjectWriterAnyTest, AnyInAnyAcceptsNull) {
2414   AnyOut out;
2415   google::protobuf::Any empty;
2416   out.mutable_any()->PackFrom(empty);
2417 
2418   EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0);
2419   ow_->StartObject("")
2420       ->StartObject("any")
2421       ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
2422       ->RenderNull("value")
2423       ->EndObject()
2424       ->EndObject();
2425   CheckOutput(out);
2426 }
2427 
2428 // {
2429 //   "any": {
2430 //     "@type": "type.googleapis.com/google.protobuf.Timestamp",
2431 //     "value": null
2432 //   }
2433 // }
TEST_P(ProtoStreamObjectWriterAnyTest,TimestampInAnyAcceptsNull)2434 TEST_P(ProtoStreamObjectWriterAnyTest, TimestampInAnyAcceptsNull) {
2435   AnyOut out;
2436   google::protobuf::Timestamp empty;
2437   out.mutable_any()->PackFrom(empty);
2438 
2439   EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0);
2440   ow_->StartObject("")
2441       ->StartObject("any")
2442       ->RenderString("@type", "type.googleapis.com/google.protobuf.Timestamp")
2443       ->RenderNull("value")
2444       ->EndObject()
2445       ->EndObject();
2446   CheckOutput(out);
2447 }
2448 
2449 // {
2450 //   "any": {
2451 //     "@type": "type.googleapis.com/google.protobuf.Duration",
2452 //     "value": null
2453 //   }
2454 // }
TEST_P(ProtoStreamObjectWriterAnyTest,DurationInAnyAcceptsNull)2455 TEST_P(ProtoStreamObjectWriterAnyTest, DurationInAnyAcceptsNull) {
2456   AnyOut out;
2457   google::protobuf::Duration empty;
2458   out.mutable_any()->PackFrom(empty);
2459 
2460   EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0);
2461   ow_->StartObject("")
2462       ->StartObject("any")
2463       ->RenderString("@type", "type.googleapis.com/google.protobuf.Duration")
2464       ->RenderNull("value")
2465       ->EndObject()
2466       ->EndObject();
2467   CheckOutput(out);
2468 }
2469 
2470 // {
2471 //   "any": {
2472 //     "@type": "type.googleapis.com/google.protobuf.FieldMask",
2473 //     "value": null
2474 //   }
2475 // }
TEST_P(ProtoStreamObjectWriterAnyTest,FieldMaskInAnyAcceptsNull)2476 TEST_P(ProtoStreamObjectWriterAnyTest, FieldMaskInAnyAcceptsNull) {
2477   AnyOut out;
2478   google::protobuf::FieldMask empty;
2479   out.mutable_any()->PackFrom(empty);
2480 
2481   EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0);
2482   ow_->StartObject("")
2483       ->StartObject("any")
2484       ->RenderString("@type", "type.googleapis.com/google.protobuf.FieldMask")
2485       ->RenderNull("value")
2486       ->EndObject()
2487       ->EndObject();
2488   CheckOutput(out);
2489 }
2490 
2491 // {
2492 //   "any": {
2493 //     "@type": "type.googleapis.com/google.protobuf.Int32Value",
2494 //     "value": null
2495 //   }
2496 // }
TEST_P(ProtoStreamObjectWriterAnyTest,WrapperInAnyAcceptsNull)2497 TEST_P(ProtoStreamObjectWriterAnyTest, WrapperInAnyAcceptsNull) {
2498   AnyOut out;
2499   google::protobuf::Int32Value empty;
2500   out.mutable_any()->PackFrom(empty);
2501 
2502   EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0);
2503   ow_->StartObject("")
2504       ->StartObject("any")
2505       ->RenderString("@type", "type.googleapis.com/google.protobuf.Int32Value")
2506       ->RenderNull("value")
2507       ->EndObject()
2508       ->EndObject();
2509   CheckOutput(out);
2510 }
2511 
2512 class ProtoStreamObjectWriterFieldMaskTest
2513     : public BaseProtoStreamObjectWriterTest {
2514  protected:
ProtoStreamObjectWriterFieldMaskTest()2515   ProtoStreamObjectWriterFieldMaskTest() {
2516     std::vector<const Descriptor*> descriptors;
2517     descriptors.push_back(FieldMaskTest::descriptor());
2518     descriptors.push_back(google::protobuf::FieldMask::descriptor());
2519     ResetTypeInfo(descriptors);
2520   }
2521 };
2522 
2523 INSTANTIATE_TEST_SUITE_P(DifferentTypeInfoSourceTest,
2524                          ProtoStreamObjectWriterFieldMaskTest,
2525                          ::testing::Values(
2526                              testing::USE_TYPE_RESOLVER));
2527 
TEST_P(ProtoStreamObjectWriterFieldMaskTest,SimpleFieldMaskTest)2528 TEST_P(ProtoStreamObjectWriterFieldMaskTest, SimpleFieldMaskTest) {
2529   FieldMaskTest expected;
2530   expected.set_id("1");
2531   expected.mutable_single_mask()->add_paths("path1");
2532 
2533   ow_->StartObject("");
2534   ow_->RenderString("id", "1");
2535   ow_->RenderString("single_mask", "path1");
2536   ow_->EndObject();
2537 
2538   CheckOutput(expected);
2539 }
2540 
TEST_P(ProtoStreamObjectWriterFieldMaskTest,MultipleMasksInCompactForm)2541 TEST_P(ProtoStreamObjectWriterFieldMaskTest, MultipleMasksInCompactForm) {
2542   FieldMaskTest expected;
2543   expected.set_id("1");
2544   expected.mutable_single_mask()->add_paths("camel_case1");
2545   expected.mutable_single_mask()->add_paths("camel_case2");
2546   expected.mutable_single_mask()->add_paths("camel_case3");
2547 
2548   ow_->StartObject("");
2549   ow_->RenderString("id", "1");
2550   ow_->RenderString("single_mask", "camelCase1,camelCase2,camelCase3");
2551   ow_->EndObject();
2552 
2553   CheckOutput(expected);
2554 }
2555 
TEST_P(ProtoStreamObjectWriterFieldMaskTest,RepeatedFieldMaskTest)2556 TEST_P(ProtoStreamObjectWriterFieldMaskTest, RepeatedFieldMaskTest) {
2557   FieldMaskTest expected;
2558   expected.set_id("1");
2559   google::protobuf::FieldMask* mask = expected.add_repeated_mask();
2560   mask->add_paths("field1");
2561   mask->add_paths("field2");
2562   expected.add_repeated_mask()->add_paths("field3");
2563 
2564   ow_->StartObject("");
2565   ow_->RenderString("id", "1");
2566   ow_->StartList("repeated_mask");
2567   ow_->RenderString("", "field1,field2");
2568   ow_->RenderString("", "field3");
2569   ow_->EndList();
2570   ow_->EndObject();
2571 
2572   CheckOutput(expected);
2573 }
2574 
TEST_P(ProtoStreamObjectWriterFieldMaskTest,EmptyFieldMaskTest)2575 TEST_P(ProtoStreamObjectWriterFieldMaskTest, EmptyFieldMaskTest) {
2576   FieldMaskTest expected;
2577   expected.set_id("1");
2578 
2579   ow_->StartObject("");
2580   ow_->RenderString("id", "1");
2581   ow_->RenderString("single_mask", "");
2582   ow_->EndObject();
2583 
2584   CheckOutput(expected);
2585 }
2586 
TEST_P(ProtoStreamObjectWriterFieldMaskTest,MaskUsingApiaryStyleShouldWork)2587 TEST_P(ProtoStreamObjectWriterFieldMaskTest, MaskUsingApiaryStyleShouldWork) {
2588   FieldMaskTest expected;
2589   expected.set_id("1");
2590 
2591   ow_->StartObject("");
2592   ow_->RenderString("id", "1");
2593   // Case1
2594   ow_->RenderString("single_mask",
2595                     "outerField(camelCase1,camelCase2,camelCase3)");
2596   expected.mutable_single_mask()->add_paths("outer_field.camel_case1");
2597   expected.mutable_single_mask()->add_paths("outer_field.camel_case2");
2598   expected.mutable_single_mask()->add_paths("outer_field.camel_case3");
2599 
2600   ow_->StartList("repeated_mask");
2601 
2602   ow_->RenderString("", "a(field1,field2)");
2603   google::protobuf::FieldMask* mask = expected.add_repeated_mask();
2604   mask->add_paths("a.field1");
2605   mask->add_paths("a.field2");
2606 
2607   ow_->RenderString("", "a(field3)");
2608   mask = expected.add_repeated_mask();
2609   mask->add_paths("a.field3");
2610 
2611   ow_->RenderString("", "a()");
2612   expected.add_repeated_mask();
2613 
2614   ow_->RenderString("", "a(,)");
2615   expected.add_repeated_mask();
2616 
2617   ow_->RenderString("", "a(field1(field2(field3)))");
2618   mask = expected.add_repeated_mask();
2619   mask->add_paths("a.field1.field2.field3");
2620 
2621   ow_->RenderString("", "a(field1(field2(field3,field4),field5),field6)");
2622   mask = expected.add_repeated_mask();
2623   mask->add_paths("a.field1.field2.field3");
2624   mask->add_paths("a.field1.field2.field4");
2625   mask->add_paths("a.field1.field5");
2626   mask->add_paths("a.field6");
2627 
2628   ow_->RenderString("", "a(id,field1(id,field2(field3,field4),field5),field6)");
2629   mask = expected.add_repeated_mask();
2630   mask->add_paths("a.id");
2631   mask->add_paths("a.field1.id");
2632   mask->add_paths("a.field1.field2.field3");
2633   mask->add_paths("a.field1.field2.field4");
2634   mask->add_paths("a.field1.field5");
2635   mask->add_paths("a.field6");
2636 
2637   ow_->RenderString("", "a(((field3,field4)))");
2638   mask = expected.add_repeated_mask();
2639   mask->add_paths("a.field3");
2640   mask->add_paths("a.field4");
2641 
2642   ow_->EndList();
2643   ow_->EndObject();
2644 
2645   CheckOutput(expected);
2646 }
2647 
TEST_P(ProtoStreamObjectWriterFieldMaskTest,MoreCloseThanOpenParentheses)2648 TEST_P(ProtoStreamObjectWriterFieldMaskTest, MoreCloseThanOpenParentheses) {
2649   EXPECT_CALL(
2650       listener_,
2651       InvalidValue(
2652           _, StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
2653           StringPiece("Field 'single_mask', Invalid FieldMask 'a(b,c))'. "
2654                             "Cannot find matching '(' for all ')'.")));
2655 
2656   ow_->StartObject("");
2657   ow_->RenderString("id", "1");
2658   ow_->RenderString("single_mask", "a(b,c))");
2659   ow_->EndObject();
2660 }
2661 
TEST_P(ProtoStreamObjectWriterFieldMaskTest,MoreOpenThanCloseParentheses)2662 TEST_P(ProtoStreamObjectWriterFieldMaskTest, MoreOpenThanCloseParentheses) {
2663   EXPECT_CALL(
2664       listener_,
2665       InvalidValue(
2666           _, StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
2667           StringPiece(
2668               "Field 'single_mask', Invalid FieldMask 'a(((b,c)'. Cannot "
2669               "find matching ')' for all '('.")));
2670 
2671   ow_->StartObject("");
2672   ow_->RenderString("id", "1");
2673   ow_->RenderString("single_mask", "a(((b,c)");
2674   ow_->EndObject();
2675 }
2676 
TEST_P(ProtoStreamObjectWriterFieldMaskTest,PathWithMapKeyShouldWork)2677 TEST_P(ProtoStreamObjectWriterFieldMaskTest, PathWithMapKeyShouldWork) {
2678   FieldMaskTest expected;
2679   expected.mutable_single_mask()->add_paths("path.to.map[\"key1\"]");
2680   expected.mutable_single_mask()->add_paths(
2681       "path.to.map[\"e\\\"[]][scape\\\"\"]");
2682   expected.mutable_single_mask()->add_paths("path.to.map[\"key2\"]");
2683 
2684   ow_->StartObject("");
2685   ow_->RenderString("single_mask",
2686                     "path.to.map[\"key1\"],path.to.map[\"e\\\"[]][scape\\\"\"],"
2687                     "path.to.map[\"key2\"]");
2688   ow_->EndObject();
2689 
2690   CheckOutput(expected);
2691 }
2692 
TEST_P(ProtoStreamObjectWriterFieldMaskTest,MapKeyMustBeAtTheEndOfAPathSegment)2693 TEST_P(ProtoStreamObjectWriterFieldMaskTest,
2694        MapKeyMustBeAtTheEndOfAPathSegment) {
2695   EXPECT_CALL(
2696       listener_,
2697       InvalidValue(
2698           _, StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
2699           StringPiece(
2700               "Field 'single_mask', Invalid FieldMask "
2701               "'path.to.map[\"key1\"]a,path.to.map[\"key2\"]'. "
2702               "Map keys should be at the end of a path segment.")));
2703 
2704   ow_->StartObject("");
2705   ow_->RenderString("single_mask",
2706                     "path.to.map[\"key1\"]a,path.to.map[\"key2\"]");
2707   ow_->EndObject();
2708 }
2709 
TEST_P(ProtoStreamObjectWriterFieldMaskTest,MapKeyMustEnd)2710 TEST_P(ProtoStreamObjectWriterFieldMaskTest, MapKeyMustEnd) {
2711   EXPECT_CALL(
2712       listener_,
2713       InvalidValue(
2714           _, StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
2715           StringPiece("Field 'single_mask', Invalid FieldMask "
2716                             "'path.to.map[\"key1\"'. Map keys should be "
2717                             "represented as [\"some_key\"].")));
2718 
2719   ow_->StartObject("");
2720   ow_->RenderString("single_mask", "path.to.map[\"key1\"");
2721   ow_->EndObject();
2722 }
2723 
TEST_P(ProtoStreamObjectWriterFieldMaskTest,MapKeyMustBeEscapedCorrectly)2724 TEST_P(ProtoStreamObjectWriterFieldMaskTest, MapKeyMustBeEscapedCorrectly) {
2725   EXPECT_CALL(
2726       listener_,
2727       InvalidValue(
2728           _, StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
2729           StringPiece("Field 'single_mask', Invalid FieldMask "
2730                             "'path.to.map[\"ke\"y1\"]'. Map keys should be "
2731                             "represented as [\"some_key\"].")));
2732 
2733   ow_->StartObject("");
2734   ow_->RenderString("single_mask", "path.to.map[\"ke\"y1\"]");
2735   ow_->EndObject();
2736 }
2737 
TEST_P(ProtoStreamObjectWriterFieldMaskTest,MapKeyCanContainAnyChars)2738 TEST_P(ProtoStreamObjectWriterFieldMaskTest, MapKeyCanContainAnyChars) {
2739   FieldMaskTest expected;
2740   expected.mutable_single_mask()->add_paths(
2741       // \xE5\xAD\x99 is the UTF-8 byte sequence for chinese character 孙.
2742       // We cannot embed non-ASCII characters in the code directly because
2743       // some windows compilers will try to interpret them using the system's
2744       // current encoding and end up with invalid UTF-8 byte sequence.
2745       "path.to.map[\"(),[],\\\"'!@#$%^&*123_|War\xE5\xAD\x99,./?><\\\\\"]");
2746   expected.mutable_single_mask()->add_paths("path.to.map[\"key2\"]");
2747 
2748   ow_->StartObject("");
2749   ow_->RenderString(
2750       "single_mask",
2751       "path.to.map[\"(),[],\\\"'!@#$%^&*123_|War\xE5\xAD\x99,./?><\\\\\"],"
2752       "path.to.map[\"key2\"]");
2753   ow_->EndObject();
2754 
2755   CheckOutput(expected);
2756 }
2757 
TEST_P(ProtoStreamObjectWriterFieldMaskTest,FieldMaskAcceptsNull)2758 TEST_P(ProtoStreamObjectWriterFieldMaskTest, FieldMaskAcceptsNull) {
2759   FieldMaskTest expected;
2760   EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0);
2761   ow_->StartObject("")->RenderNull("single_mask")->EndObject();
2762   CheckOutput(expected);
2763 }
2764 
2765 class ProtoStreamObjectWriterWrappersTest
2766     : public BaseProtoStreamObjectWriterTest {
2767  protected:
ProtoStreamObjectWriterWrappersTest()2768   ProtoStreamObjectWriterWrappersTest() {
2769     std::vector<const Descriptor*> descriptors;
2770     descriptors.push_back(Int32Wrapper::descriptor());
2771     descriptors.push_back(google::protobuf::Int32Value::descriptor());
2772     ResetTypeInfo(descriptors);
2773   }
2774 };
2775 
2776 INSTANTIATE_TEST_SUITE_P(DifferentTypeInfoSourceTest,
2777                          ProtoStreamObjectWriterWrappersTest,
2778                          ::testing::Values(
2779                              testing::USE_TYPE_RESOLVER));
2780 
TEST_P(ProtoStreamObjectWriterWrappersTest,WrapperAcceptsNull)2781 TEST_P(ProtoStreamObjectWriterWrappersTest, WrapperAcceptsNull) {
2782   Int32Wrapper wrapper;
2783   EXPECT_CALL(listener_, InvalidName(_, _, _)).Times(0);
2784   ow_->StartObject("")->RenderNull("int32")->EndObject();
2785   CheckOutput(wrapper);
2786 }
2787 
2788 class ProtoStreamObjectWriterOneOfsTest
2789     : public BaseProtoStreamObjectWriterTest {
2790  protected:
ProtoStreamObjectWriterOneOfsTest()2791   ProtoStreamObjectWriterOneOfsTest() {
2792     std::vector<const Descriptor*> descriptors;
2793     descriptors.push_back(OneOfsRequest::descriptor());
2794     descriptors.push_back(google::protobuf::Struct::descriptor());
2795     ResetTypeInfo(descriptors);
2796   }
2797 };
2798 
2799 INSTANTIATE_TEST_SUITE_P(DifferentTypeInfoSourceTest,
2800                          ProtoStreamObjectWriterOneOfsTest,
2801                          ::testing::Values(
2802                              testing::USE_TYPE_RESOLVER));
2803 
TEST_P(ProtoStreamObjectWriterOneOfsTest,MultipleOneofsFailForPrimitiveTypesTest)2804 TEST_P(ProtoStreamObjectWriterOneOfsTest,
2805        MultipleOneofsFailForPrimitiveTypesTest) {
2806   EXPECT_CALL(
2807       listener_,
2808       InvalidValue(
2809           _, StringPiece("oneof"),
2810           StringPiece(
2811               "oneof field 'data' is already set. Cannot set 'intData'")));
2812 
2813   ow_->StartObject("");
2814   ow_->RenderString("strData", "blah");
2815   ow_->RenderString("intData", "123");
2816   ow_->EndObject();
2817 }
2818 
TEST_P(ProtoStreamObjectWriterOneOfsTest,MultipleOneofsFailForMessageTypesPrimitiveFirstTest)2819 TEST_P(ProtoStreamObjectWriterOneOfsTest,
2820        MultipleOneofsFailForMessageTypesPrimitiveFirstTest) {
2821   // Test for setting primitive oneof field first and then message field.
2822   EXPECT_CALL(listener_, InvalidValue(_, StringPiece("oneof"),
2823                                       StringPiece(
2824                                           "oneof field 'data' is already set. "
2825                                           "Cannot set 'messageData'")));
2826 
2827   // JSON: { "strData": "blah", "messageData": { "dataValue": 123 } }
2828   ow_->StartObject("");
2829   ow_->RenderString("strData", "blah");
2830   ow_->StartObject("messageData");
2831   ow_->RenderInt32("dataValue", 123);
2832   ow_->EndObject();
2833   ow_->EndObject();
2834 }
2835 
TEST_P(ProtoStreamObjectWriterOneOfsTest,MultipleOneofsFailForMessageTypesMessageFirstTest)2836 TEST_P(ProtoStreamObjectWriterOneOfsTest,
2837        MultipleOneofsFailForMessageTypesMessageFirstTest) {
2838   // Test for setting message oneof field first and then primitive field.
2839   EXPECT_CALL(listener_, InvalidValue(_, StringPiece("oneof"),
2840                                       StringPiece(
2841                                           "oneof field 'data' is already set. "
2842                                           "Cannot set 'strData'")));
2843 
2844   // JSON: { "messageData": { "dataValue": 123 }, "strData": "blah" }
2845   ow_->StartObject("");
2846   ow_->StartObject("messageData");
2847   ow_->RenderInt32("dataValue", 123);
2848   ow_->EndObject();
2849   ow_->RenderString("strData", "blah");
2850   ow_->EndObject();
2851 }
2852 
TEST_P(ProtoStreamObjectWriterOneOfsTest,MultipleOneofsFailForStructTypesPrimitiveFirstTest)2853 TEST_P(ProtoStreamObjectWriterOneOfsTest,
2854        MultipleOneofsFailForStructTypesPrimitiveFirstTest) {
2855   EXPECT_CALL(listener_, InvalidValue(_, StringPiece("oneof"),
2856                                       StringPiece(
2857                                           "oneof field 'data' is already set. "
2858                                           "Cannot set 'structData'")));
2859 
2860   // JSON: { "strData": "blah", "structData": { "a": "b" } }
2861   ow_->StartObject("");
2862   ow_->RenderString("strData", "blah");
2863   ow_->StartObject("structData");
2864   ow_->RenderString("a", "b");
2865   ow_->EndObject();
2866   ow_->EndObject();
2867 }
2868 
TEST_P(ProtoStreamObjectWriterOneOfsTest,MultipleOneofsFailForStructTypesStructFirstTest)2869 TEST_P(ProtoStreamObjectWriterOneOfsTest,
2870        MultipleOneofsFailForStructTypesStructFirstTest) {
2871   EXPECT_CALL(listener_, InvalidValue(_, StringPiece("oneof"),
2872                                       StringPiece(
2873                                           "oneof field 'data' is already set. "
2874                                           "Cannot set 'strData'")));
2875 
2876   // JSON: { "structData": { "a": "b" }, "strData": "blah" }
2877   ow_->StartObject("");
2878   ow_->StartObject("structData");
2879   ow_->RenderString("a", "b");
2880   ow_->EndObject();
2881   ow_->RenderString("strData", "blah");
2882   ow_->EndObject();
2883 }
2884 
TEST_P(ProtoStreamObjectWriterOneOfsTest,MultipleOneofsFailForStructValueTypesTest)2885 TEST_P(ProtoStreamObjectWriterOneOfsTest,
2886        MultipleOneofsFailForStructValueTypesTest) {
2887   EXPECT_CALL(listener_, InvalidValue(_, StringPiece("oneof"),
2888                                       StringPiece(
2889                                           "oneof field 'data' is already set. "
2890                                           "Cannot set 'valueData'")));
2891 
2892   // JSON: { "messageData": { "dataValue": 123 }, "valueData": { "a": "b" } }
2893   ow_->StartObject("");
2894   ow_->StartObject("messageData");
2895   ow_->RenderInt32("dataValue", 123);
2896   ow_->EndObject();
2897   ow_->StartObject("valueData");
2898   ow_->RenderString("a", "b");
2899   ow_->EndObject();
2900   ow_->EndObject();
2901 }
2902 
TEST_P(ProtoStreamObjectWriterOneOfsTest,MultipleOneofsFailForWellKnownTypesPrimitiveFirstTest)2903 TEST_P(ProtoStreamObjectWriterOneOfsTest,
2904        MultipleOneofsFailForWellKnownTypesPrimitiveFirstTest) {
2905   EXPECT_CALL(listener_, InvalidValue(_, StringPiece("oneof"),
2906                                       StringPiece(
2907                                           "oneof field 'data' is already set. "
2908                                           "Cannot set 'tsData'")));
2909 
2910   // JSON: { "intData": 123, "tsData": "1970-01-02T01:00:00.000Z" }
2911   ow_->StartObject("");
2912   ow_->RenderInt32("intData", 123);
2913   ow_->RenderString("tsData", "1970-01-02T01:00:00.000Z");
2914   ow_->EndObject();
2915 }
2916 
TEST_P(ProtoStreamObjectWriterOneOfsTest,MultipleOneofsFailForWellKnownTypesWktFirstTest)2917 TEST_P(ProtoStreamObjectWriterOneOfsTest,
2918        MultipleOneofsFailForWellKnownTypesWktFirstTest) {
2919   EXPECT_CALL(listener_, InvalidValue(_, StringPiece("oneof"),
2920                                       StringPiece(
2921                                           "oneof field 'data' is already set. "
2922                                           "Cannot set 'intData'")));
2923 
2924   // JSON: { "tsData": "1970-01-02T01:00:00.000Z", "intData": 123 }
2925   ow_->StartObject("");
2926   ow_->RenderString("tsData", "1970-01-02T01:00:00.000Z");
2927   ow_->RenderInt32("intData", 123);
2928   ow_->EndObject();
2929 }
2930 
TEST_P(ProtoStreamObjectWriterOneOfsTest,MultipleOneofsFailForWellKnownTypesAndMessageTest)2931 TEST_P(ProtoStreamObjectWriterOneOfsTest,
2932        MultipleOneofsFailForWellKnownTypesAndMessageTest) {
2933   EXPECT_CALL(listener_, InvalidValue(_, StringPiece("oneof"),
2934                                       StringPiece(
2935                                           "oneof field 'data' is already set. "
2936                                           "Cannot set 'messageData'")));
2937 
2938   // JSON: { "tsData": "1970-01-02T01:00:00.000Z",
2939   //         "messageData": { "dataValue": 123 } }
2940   ow_->StartObject("");
2941   ow_->RenderString("tsData", "1970-01-02T01:00:00.000Z");
2942   ow_->StartObject("messageData");
2943   ow_->RenderInt32("dataValue", 123);
2944   ow_->EndObject();
2945   ow_->EndObject();
2946 }
2947 
TEST_P(ProtoStreamObjectWriterOneOfsTest,MultipleOneofsFailForOneofWithinAnyTest)2948 TEST_P(ProtoStreamObjectWriterOneOfsTest,
2949        MultipleOneofsFailForOneofWithinAnyTest) {
2950   EXPECT_CALL(listener_, InvalidValue(_, StringPiece("oneof"),
2951                                       StringPiece(
2952                                           "oneof field 'data' is already set. "
2953                                           "Cannot set 'intData'")));
2954 
2955   // JSON:
2956   // { "anyData":
2957   //    { "@type":
2958   //       "type.googleapis.com/proto_util_converter.testing.oneofs.OneOfsRequest",
2959   //     "strData": "blah",
2960   //     "intData": 123
2961   //    }
2962   // }
2963   ow_->StartObject("");
2964   ow_->StartObject("anyData");
2965   ow_->RenderString(
2966       "@type",
2967       "type.googleapis.com/proto_util_converter.testing.oneofs.OneOfsRequest");
2968   ow_->RenderString("strData", "blah");
2969   ow_->RenderInt32("intData", 123);
2970   ow_->EndObject();
2971   ow_->EndObject();
2972 }
2973 
2974 }  // namespace converter
2975 }  // namespace util
2976 }  // namespace protobuf
2977 }  // namespace google
2978