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