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