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