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