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