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


libaditof
Author(s):
autogenerated on Wed May 21 2025 02:06:58