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