blob: 41eaebc091051aa9389c9337fc52aaeb751860d9 [file] [log] [blame]
Feng Xiaoe96ff302015-06-15 18:21:48 -07001// 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>
Jisi Liu46e8ff62015-10-05 11:59:43 -070048#include <google/protobuf/util/message_differencer.h>
Feng Xiaoe96ff302015-06-15 18:21:48 -070049#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>
Feng Xiaoeee38b02015-08-22 18:25:48 -070053#include <google/protobuf/util/internal/testdata/oneofs.pb.h>
Feng Xiaoe96ff302015-06-15 18:21:48 -070054#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
59namespace google {
60namespace protobuf {
61namespace util {
62namespace converter {
63
64using google::protobuf::testing::Author;
65using google::protobuf::testing::Book;
66using google::protobuf::testing::Book_Data;
67using google::protobuf::testing::Primitive;
68using google::protobuf::testing::Publisher;
69using google::protobuf::Descriptor;
70using google::protobuf::DescriptorPool;
71using google::protobuf::DynamicMessageFactory;
72using google::protobuf::FileDescriptorProto;
73using google::protobuf::Message;
74using google::protobuf::io::ArrayInputStream;
75using strings::GrowingArrayByteSink;
76using ::testing::_;
77using ::testing::Args;
78using google::protobuf::testing::anys::AnyM;
79using google::protobuf::testing::anys::AnyOut;
Feng Xiaoeee38b02015-08-22 18:25:48 -070080using google::protobuf::testing::oneofs::OneOfsRequest;
Feng Xiaoe96ff302015-06-15 18:21:48 -070081using google::protobuf::testing::FieldMaskTest;
82using google::protobuf::testing::maps::MapIn;
83using google::protobuf::testing::structs::StructType;
84using google::protobuf::testing::timestampduration::TimestampDuration;
85
86
87namespace {
88string GetTypeUrl(const Descriptor* descriptor) {
89 return string(kTypeServiceBaseUrl) + "/" + descriptor->full_name();
90}
91} // namespace
92
Jisi Liu3b3c8ab2016-03-30 11:39:59 -070093#if __cplusplus >= 201103L
94 using std::get;
95#else
96 using std::tr1::get;
97#endif
98
Feng Xiaoe96ff302015-06-15 18:21:48 -070099class BaseProtoStreamObjectWriterTest
100 : public ::testing::TestWithParam<testing::TypeInfoSource> {
101 protected:
102 BaseProtoStreamObjectWriterTest()
103 : helper_(GetParam()),
104 listener_(),
105 output_(new GrowingArrayByteSink(1000)),
106 ow_() {}
107
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
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
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(),
Jisi Liu3b3c8ab2016-03-30 11:39:59 -0700131 &listener_, options_));
132 }
133
134 void ResetTypeInfo(const Descriptor* descriptor) {
135 vector<const Descriptor*> descriptors;
136 descriptors.push_back(descriptor);
137 ResetTypeInfo(descriptors);
Feng Xiaoe96ff302015-06-15 18:21:48 -0700138 }
139
140 virtual ~BaseProtoStreamObjectWriterTest() {}
141
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
Jisi Liu46e8ff62015-10-05 11:59:43 -0700155 if (!MessageDifferencer::Equivalent(expected, *message)) {
156 EXPECT_EQ(expected.DebugString(), message->DebugString());
157 }
Feng Xiaoe96ff302015-06-15 18:21:48 -0700158 }
159
160 void CheckOutput(const Message& expected) { CheckOutput(expected, -1); }
161
162 const google::protobuf::Type* GetType(const Descriptor* descriptor) {
Feng Xiaoeee38b02015-08-22 18:25:48 -0700163 return helper_.GetTypeInfo()->GetTypeByTypeUrl(GetTypeUrl(descriptor));
Feng Xiaoe96ff302015-06-15 18:21:48 -0700164 }
165
166 testing::TypeInfoTestHelper helper_;
167 MockErrorListener listener_;
168 google::protobuf::scoped_ptr<GrowingArrayByteSink> output_;
169 google::protobuf::scoped_ptr<ProtoStreamObjectWriter> ow_;
Jisi Liu3b3c8ab2016-03-30 11:39:59 -0700170 ProtoStreamObjectWriter::Options options_;
Feng Xiaoe96ff302015-06-15 18:21:48 -0700171};
172
173MATCHER_P(HasObjectLocation, expected,
174 "Verifies the expected object location") {
Jisi Liu3b3c8ab2016-03-30 11:39:59 -0700175 string actual = get<0>(arg).ToString();
Feng Xiaoe96ff302015-06-15 18:21:48 -0700176 if (actual.compare(expected) == 0) return true;
177 *result_listener << "actual location is: " << actual;
178 return false;
179}
180
181class ProtoStreamObjectWriterTest : public BaseProtoStreamObjectWriterTest {
182 protected:
183 ProtoStreamObjectWriterTest()
184 : BaseProtoStreamObjectWriterTest(Book::descriptor()) {}
185
186 virtual ~ProtoStreamObjectWriterTest() {}
187};
188
189INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
190 ProtoStreamObjectWriterTest,
191 ::testing::Values(
192 testing::USE_TYPE_RESOLVER));
193
194TEST_P(ProtoStreamObjectWriterTest, EmptyObject) {
195 Book empty;
196 ow_->StartObject("")->EndObject();
197 CheckOutput(empty, 0);
198}
199
200TEST_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
216TEST_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
Feng Xiaoe841bac2015-12-11 17:09:20 -0800252TEST_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
Feng Xiaoe96ff302015-06-15 18:21:48 -0700267TEST_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
Jisi Liu3b3c8ab2016-03-30 11:39:59 -0700300 ResetTypeInfo(Primitive::descriptor());
Feng Xiaoe96ff302015-06-15 18:21:48 -0700301
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
367TEST_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
Jisi Liu3b3c8ab2016-03-30 11:39:59 -0700373 ResetTypeInfo(Primitive::descriptor());
Feng Xiaoe96ff302015-06-15 18:21:48 -0700374
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
400TEST_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
Jisi Liu3b3c8ab2016-03-30 11:39:59 -0700406 ResetTypeInfo(Primitive::descriptor());
Feng Xiaoe96ff302015-06-15 18:21:48 -0700407
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
434TEST_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
451TEST_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
466TEST_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
485TEST_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
506TEST_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
531TEST_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
553TEST_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
580TEST_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
607TEST_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
617TEST_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
651TEST_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
661TEST_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
682TEST_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
692TEST_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
712TEST_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
727TEST_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
737TEST_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
755TEST_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
766TEST_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
784TEST_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
800TEST_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
812TEST_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("")));
Feng Xiaoe96ff302015-06-15 18:21:48 -0700819 ow_->StartList("oops")->RenderString("", "item")->EndList();
820 CheckOutput(empty, 0);
821}
822
823TEST_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
834TEST_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
845TEST_P(ProtoStreamObjectWriterTest, NullValue) {
846 Book empty;
847
848 ow_->RenderNull("");
849 CheckOutput(empty, 0);
850}
851
852TEST_P(ProtoStreamObjectWriterTest, NullValueForMessageField) {
853 Book empty;
854
855 ow_->RenderNull("author");
856 CheckOutput(empty, 0);
857}
858
859TEST_P(ProtoStreamObjectWriterTest, NullValueForPrimitiveField) {
860 Book empty;
861
862 ow_->RenderNull("length");
863 CheckOutput(empty, 0);
864}
865
866class ProtoStreamObjectWriterTimestampDurationTest
867 : public BaseProtoStreamObjectWriterTest {
868 protected:
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
Jisi Liu46e8ff62015-10-05 11:59:43 -0700878INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
879 ProtoStreamObjectWriterTimestampDurationTest,
880 ::testing::Values(
881 testing::USE_TYPE_RESOLVER));
882
Feng Xiaoe841bac2015-12-11 17:09:20 -0800883TEST_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
Jisi Liu3b3c8ab2016-03-30 11:39:59 -0700895TEST_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
908TEST_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
921TEST_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
934TEST_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
947TEST_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
962TEST_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
979TEST_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
996TEST_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
Feng Xiaoe96ff302015-06-15 18:21:48 -07001013TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError1) {
1014 TimestampDuration timestamp;
1015
1016 EXPECT_CALL(
1017 listener_,
Jisi Liu46e8ff62015-10-05 11:59:43 -07001018 InvalidValue(_,
1019 StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
1020 StringPiece("Field 'ts', Invalid time format: ")));
Feng Xiaoe96ff302015-06-15 18:21:48 -07001021
1022 ow_->StartObject("")->RenderString("ts", "")->EndObject();
1023 CheckOutput(timestamp);
1024}
1025
1026TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError2) {
1027 TimestampDuration timestamp;
1028
1029 EXPECT_CALL(
1030 listener_,
Jisi Liu46e8ff62015-10-05 11:59:43 -07001031 InvalidValue(_,
1032 StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
1033 StringPiece("Field 'ts', Invalid time format: Z")));
Feng Xiaoe96ff302015-06-15 18:21:48 -07001034
1035 ow_->StartObject("")->RenderString("ts", "Z")->EndObject();
1036 CheckOutput(timestamp);
1037}
1038
1039TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError3) {
1040 TimestampDuration timestamp;
1041
1042 EXPECT_CALL(
1043 listener_,
Jisi Liu46e8ff62015-10-05 11:59:43 -07001044 InvalidValue(_,
1045 StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
1046 StringPiece("Field 'ts', Invalid time format: "
1047 "1970-01-01T00:00:00.ABZ")));
Feng Xiaoe96ff302015-06-15 18:21:48 -07001048
1049 ow_->StartObject("")
1050 ->RenderString("ts", "1970-01-01T00:00:00.ABZ")
1051 ->EndObject();
1052 CheckOutput(timestamp);
1053}
1054
1055TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError4) {
1056 TimestampDuration timestamp;
1057
1058 EXPECT_CALL(
1059 listener_,
1060 InvalidValue(_,
1061 StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
Jisi Liu46e8ff62015-10-05 11:59:43 -07001062 StringPiece("Field 'ts', Invalid time format: "
Jisi Liu3b3c8ab2016-03-30 11:39:59 -07001063 "-8031-10-18T00:00:00.000Z")));
Feng Xiaoe96ff302015-06-15 18:21:48 -07001064
1065 ow_->StartObject("")
Jisi Liu3b3c8ab2016-03-30 11:39:59 -07001066 ->RenderString("ts", "-8031-10-18T00:00:00.000Z")
Feng Xiaoe96ff302015-06-15 18:21:48 -07001067 ->EndObject();
1068 CheckOutput(timestamp);
1069}
1070
Feng Xiaoe841bac2015-12-11 17:09:20 -08001071TEST_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
1088TEST_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
1105TEST_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
Jisi Liu3b3c8ab2016-03-30 11:39:59 -07001122TEST_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
Feng Xiaoe841bac2015-12-11 17:09:20 -08001138TEST_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}
Feng Xiaoe96ff302015-06-15 18:21:48 -07001147
1148TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError1) {
1149 TimestampDuration duration;
1150
1151 EXPECT_CALL(
1152 listener_,
Feng Xiaoeee38b02015-08-22 18:25:48 -07001153 InvalidValue(
1154 _, StringPiece("type.googleapis.com/google.protobuf.Duration"),
1155 StringPiece("Field 'dur', Illegal duration format; duration must "
1156 "end with 's'")));
Feng Xiaoe96ff302015-06-15 18:21:48 -07001157
1158 ow_->StartObject("")->RenderString("dur", "")->EndObject();
1159 CheckOutput(duration);
1160}
1161
1162TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError2) {
1163 TimestampDuration duration;
1164
1165 EXPECT_CALL(
1166 listener_,
Feng Xiaoeee38b02015-08-22 18:25:48 -07001167 InvalidValue(
1168 _, StringPiece("type.googleapis.com/google.protobuf.Duration"),
1169 StringPiece("Field 'dur', Invalid duration format, failed to parse "
1170 "seconds")));
Feng Xiaoe96ff302015-06-15 18:21:48 -07001171
1172 ow_->StartObject("")->RenderString("dur", "s")->EndObject();
1173 CheckOutput(duration);
1174}
1175
1176TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError3) {
1177 TimestampDuration duration;
1178
1179 EXPECT_CALL(
1180 listener_,
Feng Xiaoeee38b02015-08-22 18:25:48 -07001181 InvalidValue(
1182 _, StringPiece("type.googleapis.com/google.protobuf.Duration"),
1183 StringPiece("Field 'dur', Invalid duration format, failed to "
Feng Xiaoe841bac2015-12-11 17:09:20 -08001184 "parse nano seconds")));
Feng Xiaoe96ff302015-06-15 18:21:48 -07001185
1186 ow_->StartObject("")->RenderString("dur", "123.DEFs")->EndObject();
1187 CheckOutput(duration);
1188}
1189
1190TEST_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
Feng Xiaoe841bac2015-12-11 17:09:20 -08001203TEST_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
Feng Xiaoe96ff302015-06-15 18:21:48 -07001216TEST_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
1230TEST_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
1244class ProtoStreamObjectWriterStructTest
1245 : public BaseProtoStreamObjectWriterTest {
1246 protected:
Jisi Liu3b3c8ab2016-03-30 11:39:59 -07001247 ProtoStreamObjectWriterStructTest() { ResetProtoWriter(); }
1248
1249 // Resets ProtoWriter with current set of options and other state.
1250 void ResetProtoWriter() {
Feng Xiaoe96ff302015-06-15 18:21:48 -07001251 vector<const Descriptor*> descriptors;
1252 descriptors.push_back(StructType::descriptor());
1253 descriptors.push_back(google::protobuf::Struct::descriptor());
1254 ResetTypeInfo(descriptors);
1255 }
1256};
1257
Jisi Liu46e8ff62015-10-05 11:59:43 -07001258INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
1259 ProtoStreamObjectWriterStructTest,
1260 ::testing::Values(
1261 testing::USE_TYPE_RESOLVER));
1262
Feng Xiaoe96ff302015-06-15 18:21:48 -07001263// TODO(skarvaje): Write tests for failure cases.
1264TEST_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
1279TEST_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
1289TEST_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
Jisi Liu46e8ff62015-10-05 11:59:43 -07001301TEST_P(ProtoStreamObjectWriterStructTest, SimpleRepeatedStructMapKeyTest) {
1302 EXPECT_CALL(
1303 listener_,
Feng Xiaoe841bac2015-12-11 17:09:20 -08001304 InvalidName(_, StringPiece("gBike"),
1305 StringPiece("Repeated map key: 'gBike' is already set.")));
Jisi Liu46e8ff62015-10-05 11:59:43 -07001306 ow_->StartObject("")
1307 ->StartObject("object")
Feng Xiaoe841bac2015-12-11 17:09:20 -08001308 ->RenderString("gBike", "v1")
1309 ->RenderString("gBike", "v2")
Jisi Liu46e8ff62015-10-05 11:59:43 -07001310 ->EndObject()
1311 ->EndObject();
1312}
1313
1314TEST_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
1329TEST_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
Jisi Liu3b3c8ab2016-03-30 11:39:59 -07001346TEST_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
Feng Xiaoe96ff302015-06-15 18:21:48 -07001368class ProtoStreamObjectWriterMapTest : public BaseProtoStreamObjectWriterTest {
1369 protected:
1370 ProtoStreamObjectWriterMapTest()
1371 : BaseProtoStreamObjectWriterTest(MapIn::descriptor()) {}
1372};
1373
Jisi Liu46e8ff62015-10-05 11:59:43 -07001374INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
1375 ProtoStreamObjectWriterMapTest,
1376 ::testing::Values(
1377 testing::USE_TYPE_RESOLVER));
1378
Feng Xiaoe96ff302015-06-15 18:21:48 -07001379TEST_P(ProtoStreamObjectWriterMapTest, MapShouldNotAcceptList) {
1380 MapIn mm;
Feng Xiaoe841bac2015-12-11 17:09:20 -08001381 EXPECT_CALL(
1382 listener_,
1383 InvalidValue(
1384 _, StringPiece("Map"),
1385 StringPiece("Cannot bind a list to map for field 'map_input'.")));
Feng Xiaoe96ff302015-06-15 18:21:48 -07001386 ow_->StartObject("")
1387 ->StartList("map_input")
1388 ->RenderString("a", "b")
1389 ->EndList()
1390 ->EndObject();
1391 CheckOutput(mm);
1392}
1393
Jisi Liu46e8ff62015-10-05 11:59:43 -07001394TEST_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
Feng Xiaoe96ff302015-06-15 18:21:48 -07001408class ProtoStreamObjectWriterAnyTest : public BaseProtoStreamObjectWriterTest {
1409 protected:
1410 ProtoStreamObjectWriterAnyTest() {
1411 vector<const Descriptor*> descriptors;
1412 descriptors.push_back(AnyOut::descriptor());
1413 descriptors.push_back(google::protobuf::DoubleValue::descriptor());
Jisi Liu46e8ff62015-10-05 11:59:43 -07001414 descriptors.push_back(google::protobuf::Timestamp::descriptor());
Feng Xiaoe96ff302015-06-15 18:21:48 -07001415 descriptors.push_back(google::protobuf::Any::descriptor());
1416 ResetTypeInfo(descriptors);
1417 }
1418};
1419
Jisi Liu46e8ff62015-10-05 11:59:43 -07001420INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
1421 ProtoStreamObjectWriterAnyTest,
1422 ::testing::Values(
1423 testing::USE_TYPE_RESOLVER));
1424
Feng Xiaoe96ff302015-06-15 18:21:48 -07001425TEST_P(ProtoStreamObjectWriterAnyTest, AnyRenderSuccess) {
1426 AnyOut any;
1427 google::protobuf::Any* any_type = any.mutable_any();
1428 any_type->set_type_url("type.googleapis.com/google.protobuf.DoubleValue");
1429 google::protobuf::DoubleValue d;
1430 d.set_value(40.2);
1431 any_type->set_value(d.SerializeAsString());
1432
1433 ow_->StartObject("")
1434 ->StartObject("any")
1435 ->RenderString("@type", "type.googleapis.com/google.protobuf.DoubleValue")
1436 ->RenderDouble("value", 40.2)
1437 ->EndObject()
1438 ->EndObject();
1439 CheckOutput(any);
1440}
1441
1442TEST_P(ProtoStreamObjectWriterAnyTest, RecursiveAny) {
1443 AnyOut out;
1444 ::google::protobuf::Any* any = out.mutable_any();
1445 any->set_type_url("type.googleapis.com/google.protobuf.Any");
1446
1447 ::google::protobuf::Any nested_any;
1448 nested_any.set_type_url(
1449 "type.googleapis.com/google.protobuf.testing.anys.AnyM");
1450
1451 AnyM m;
1452 m.set_foo("foovalue");
1453 nested_any.set_value(m.SerializeAsString());
1454
1455 any->set_value(nested_any.SerializeAsString());
1456
1457 ow_->StartObject("")
1458 ->StartObject("any")
1459 ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
1460 ->StartObject("value")
1461 ->RenderString("@type",
1462 "type.googleapis.com/google.protobuf.testing.anys.AnyM")
1463 ->RenderString("foo", "foovalue")
1464 ->EndObject()
1465 ->EndObject()
1466 ->EndObject();
Feng Xiaoe96ff302015-06-15 18:21:48 -07001467}
1468
1469TEST_P(ProtoStreamObjectWriterAnyTest, DoubleRecursiveAny) {
1470 AnyOut out;
1471 ::google::protobuf::Any* any = out.mutable_any();
1472 any->set_type_url("type.googleapis.com/google.protobuf.Any");
1473
1474 ::google::protobuf::Any nested_any;
1475 nested_any.set_type_url("type.googleapis.com/google.protobuf.Any");
1476
1477 ::google::protobuf::Any second_nested_any;
1478 second_nested_any.set_type_url(
1479 "type.googleapis.com/google.protobuf.testing.anys.AnyM");
1480
1481 AnyM m;
1482 m.set_foo("foovalue");
1483 second_nested_any.set_value(m.SerializeAsString());
1484
1485 nested_any.set_value(second_nested_any.SerializeAsString());
1486 any->set_value(nested_any.SerializeAsString());
1487
1488 ow_->StartObject("")
1489 ->StartObject("any")
1490 ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
1491 ->StartObject("value")
1492 ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
1493 ->StartObject("value")
1494 ->RenderString("@type",
1495 "type.googleapis.com/google.protobuf.testing.anys.AnyM")
1496 ->RenderString("foo", "foovalue")
1497 ->EndObject()
1498 ->EndObject()
1499 ->EndObject()
1500 ->EndObject();
Feng Xiaoe96ff302015-06-15 18:21:48 -07001501}
1502
1503TEST_P(ProtoStreamObjectWriterAnyTest, EmptyAnyFromEmptyObject) {
1504 AnyOut out;
1505 out.mutable_any();
1506
1507 ow_->StartObject("")->StartObject("any")->EndObject()->EndObject();
1508
1509 CheckOutput(out, 2);
1510}
1511
1512TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails1) {
1513 AnyOut any;
1514
Feng Xiaoeee38b02015-08-22 18:25:48 -07001515 EXPECT_CALL(
1516 listener_,
1517 InvalidValue(_, StringPiece("Any"),
1518 StringPiece("Missing or invalid @type for any field in "
Feng Xiaoe96ff302015-06-15 18:21:48 -07001519 "google.protobuf.testing.anys.AnyOut")));
1520
1521 ow_->StartObject("")
1522 ->StartObject("any")
1523 ->StartObject("another")
1524 ->EndObject()
1525 ->EndObject()
1526 ->EndObject();
1527 CheckOutput(any);
1528}
1529
1530TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails2) {
1531 AnyOut any;
1532
Feng Xiaoeee38b02015-08-22 18:25:48 -07001533 EXPECT_CALL(
1534 listener_,
1535 InvalidValue(_, StringPiece("Any"),
1536 StringPiece("Missing or invalid @type for any field in "
Feng Xiaoe96ff302015-06-15 18:21:48 -07001537 "google.protobuf.testing.anys.AnyOut")));
1538
1539 ow_->StartObject("")
1540 ->StartObject("any")
1541 ->StartList("another")
1542 ->EndObject()
1543 ->EndObject()
1544 ->EndObject();
1545 CheckOutput(any);
1546}
1547
1548TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails3) {
1549 AnyOut any;
1550
Feng Xiaoeee38b02015-08-22 18:25:48 -07001551 EXPECT_CALL(
1552 listener_,
1553 InvalidValue(_, StringPiece("Any"),
1554 StringPiece("Missing or invalid @type for any field in "
Feng Xiaoe96ff302015-06-15 18:21:48 -07001555 "google.protobuf.testing.anys.AnyOut")));
1556
1557 ow_->StartObject("")
1558 ->StartObject("any")
1559 ->RenderString("value", "somevalue")
1560 ->EndObject()
1561 ->EndObject();
1562 CheckOutput(any);
1563}
1564
1565TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithInvalidTypeUrlFails) {
1566 AnyOut any;
1567
Feng Xiaoeee38b02015-08-22 18:25:48 -07001568 EXPECT_CALL(listener_,
1569 InvalidValue(
1570 _, StringPiece("Any"),
1571 StringPiece("Invalid type URL, type URLs must be of the form "
1572 "'type.googleapis.com/<typename>', got: "
1573 "type.other.com/some.Type")));
Feng Xiaoe96ff302015-06-15 18:21:48 -07001574
1575 ow_->StartObject("")
1576 ->StartObject("any")
1577 ->RenderString("@type", "type.other.com/some.Type")
1578 ->RenderDouble("value", 40.2)
1579 ->EndObject()
1580 ->EndObject();
1581 CheckOutput(any);
1582}
1583
1584TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithUnknownTypeFails) {
1585 AnyOut any;
1586
1587 EXPECT_CALL(
1588 listener_,
1589 InvalidValue(_, StringPiece("Any"),
1590 StringPiece("Invalid type URL, unknown type: some.Type")));
1591 ow_->StartObject("")
1592 ->StartObject("any")
1593 ->RenderString("@type", "type.googleapis.com/some.Type")
1594 ->RenderDouble("value", 40.2)
1595 ->EndObject()
1596 ->EndObject();
1597 CheckOutput(any);
1598}
1599
1600TEST_P(ProtoStreamObjectWriterAnyTest, AnyNullInputFails) {
1601 AnyOut any;
1602
1603 ow_->StartObject("")->RenderNull("any")->EndObject();
1604 CheckOutput(any);
1605}
1606
Jisi Liu46e8ff62015-10-05 11:59:43 -07001607TEST_P(ProtoStreamObjectWriterAnyTest, AnyWellKnownTypeErrorTest) {
1608 EXPECT_CALL(listener_, InvalidValue(_, StringPiece("Any"),
1609 StringPiece("Invalid time format: ")));
1610
1611 AnyOut any;
1612 google::protobuf::Any* any_type = any.mutable_any();
1613 any_type->set_type_url("type.googleapis.com/google.protobuf.Timestamp");
1614
1615 ow_->StartObject("")
1616 ->StartObject("any")
1617 ->RenderString("@type", "type.googleapis.com/google.protobuf.Timestamp")
1618 ->RenderString("value", "")
1619 ->EndObject()
1620 ->EndObject();
1621 CheckOutput(any);
1622}
1623
Feng Xiaoe96ff302015-06-15 18:21:48 -07001624class ProtoStreamObjectWriterFieldMaskTest
1625 : public BaseProtoStreamObjectWriterTest {
1626 protected:
1627 ProtoStreamObjectWriterFieldMaskTest() {
1628 vector<const Descriptor*> descriptors;
1629 descriptors.push_back(FieldMaskTest::descriptor());
1630 descriptors.push_back(google::protobuf::FieldMask::descriptor());
1631 ResetTypeInfo(descriptors);
1632 }
1633};
1634
Jisi Liu46e8ff62015-10-05 11:59:43 -07001635INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
1636 ProtoStreamObjectWriterFieldMaskTest,
1637 ::testing::Values(
1638 testing::USE_TYPE_RESOLVER));
1639
Feng Xiaoe96ff302015-06-15 18:21:48 -07001640TEST_P(ProtoStreamObjectWriterFieldMaskTest, SimpleFieldMaskTest) {
1641 FieldMaskTest expected;
1642 expected.set_id("1");
1643 expected.mutable_single_mask()->add_paths("path1");
1644
1645 ow_->StartObject("");
1646 ow_->RenderString("id", "1");
1647 ow_->RenderString("single_mask", "path1");
1648 ow_->EndObject();
1649
1650 CheckOutput(expected);
1651}
1652
1653TEST_P(ProtoStreamObjectWriterFieldMaskTest, MutipleMasksInCompactForm) {
1654 FieldMaskTest expected;
1655 expected.set_id("1");
1656 expected.mutable_single_mask()->add_paths("camel_case1");
1657 expected.mutable_single_mask()->add_paths("camel_case2");
1658 expected.mutable_single_mask()->add_paths("camel_case3");
1659
1660 ow_->StartObject("");
1661 ow_->RenderString("id", "1");
1662 ow_->RenderString("single_mask", "camelCase1,camelCase2,camelCase3");
1663 ow_->EndObject();
1664
1665 CheckOutput(expected);
1666}
1667
1668TEST_P(ProtoStreamObjectWriterFieldMaskTest, RepeatedFieldMaskTest) {
1669 FieldMaskTest expected;
1670 expected.set_id("1");
1671 google::protobuf::FieldMask* mask = expected.add_repeated_mask();
1672 mask->add_paths("field1");
1673 mask->add_paths("field2");
1674 expected.add_repeated_mask()->add_paths("field3");
1675
1676 ow_->StartObject("");
1677 ow_->RenderString("id", "1");
1678 ow_->StartList("repeated_mask");
1679 ow_->RenderString("", "field1,field2");
1680 ow_->RenderString("", "field3");
1681 ow_->EndList();
1682 ow_->EndObject();
1683
1684 CheckOutput(expected);
1685}
1686
1687TEST_P(ProtoStreamObjectWriterFieldMaskTest, EmptyFieldMaskTest) {
1688 FieldMaskTest expected;
1689 expected.set_id("1");
1690
1691 ow_->StartObject("");
1692 ow_->RenderString("id", "1");
1693 ow_->RenderString("single_mask", "");
1694 ow_->EndObject();
1695
1696 CheckOutput(expected);
1697}
1698
1699TEST_P(ProtoStreamObjectWriterFieldMaskTest, MaskUsingApiaryStyleShouldWork) {
1700 FieldMaskTest expected;
1701 expected.set_id("1");
1702
1703 ow_->StartObject("");
1704 ow_->RenderString("id", "1");
1705 // Case1
1706 ow_->RenderString("single_mask",
1707 "outerField(camelCase1,camelCase2,camelCase3)");
1708 expected.mutable_single_mask()->add_paths("outer_field.camel_case1");
1709 expected.mutable_single_mask()->add_paths("outer_field.camel_case2");
1710 expected.mutable_single_mask()->add_paths("outer_field.camel_case3");
1711
1712 ow_->StartList("repeated_mask");
1713
1714 ow_->RenderString("", "a(field1,field2)");
1715 google::protobuf::FieldMask* mask = expected.add_repeated_mask();
1716 mask->add_paths("a.field1");
1717 mask->add_paths("a.field2");
1718
1719 ow_->RenderString("", "a(field3)");
1720 mask = expected.add_repeated_mask();
1721 mask->add_paths("a.field3");
1722
1723 ow_->RenderString("", "a()");
1724 expected.add_repeated_mask();
1725
1726 ow_->RenderString("", "a(,)");
1727 expected.add_repeated_mask();
1728
1729 ow_->RenderString("", "a(field1(field2(field3)))");
1730 mask = expected.add_repeated_mask();
1731 mask->add_paths("a.field1.field2.field3");
1732
1733 ow_->RenderString("", "a(field1(field2(field3,field4),field5),field6)");
1734 mask = expected.add_repeated_mask();
1735 mask->add_paths("a.field1.field2.field3");
1736 mask->add_paths("a.field1.field2.field4");
1737 mask->add_paths("a.field1.field5");
1738 mask->add_paths("a.field6");
1739
1740 ow_->RenderString("", "a(id,field1(id,field2(field3,field4),field5),field6)");
1741 mask = expected.add_repeated_mask();
1742 mask->add_paths("a.id");
1743 mask->add_paths("a.field1.id");
1744 mask->add_paths("a.field1.field2.field3");
1745 mask->add_paths("a.field1.field2.field4");
1746 mask->add_paths("a.field1.field5");
1747 mask->add_paths("a.field6");
1748
1749 ow_->RenderString("", "a(((field3,field4)))");
1750 mask = expected.add_repeated_mask();
1751 mask->add_paths("a.field3");
1752 mask->add_paths("a.field4");
1753
1754 ow_->EndList();
1755 ow_->EndObject();
1756
1757 CheckOutput(expected);
1758}
1759
1760TEST_P(ProtoStreamObjectWriterFieldMaskTest, MoreCloseThanOpenParentheses) {
1761 EXPECT_CALL(
1762 listener_,
Feng Xiaoeee38b02015-08-22 18:25:48 -07001763 InvalidValue(
1764 _, StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
1765 StringPiece("Field 'single_mask', Invalid FieldMask 'a(b,c))'. "
1766 "Cannot find matching '(' for all ')'.")));
Feng Xiaoe96ff302015-06-15 18:21:48 -07001767
1768 ow_->StartObject("");
1769 ow_->RenderString("id", "1");
1770 ow_->RenderString("single_mask", "a(b,c))");
1771 ow_->EndObject();
1772}
1773
1774TEST_P(ProtoStreamObjectWriterFieldMaskTest, MoreOpenThanCloseParentheses) {
1775 EXPECT_CALL(
1776 listener_,
1777 InvalidValue(
1778 _, StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
1779 StringPiece(
1780 "Field 'single_mask', Invalid FieldMask 'a(((b,c)'. Cannot "
1781 "find matching ')' for all '('.")));
1782
1783 ow_->StartObject("");
1784 ow_->RenderString("id", "1");
1785 ow_->RenderString("single_mask", "a(((b,c)");
1786 ow_->EndObject();
1787}
1788
1789TEST_P(ProtoStreamObjectWriterFieldMaskTest, PathWithMapKeyShouldWork) {
1790 FieldMaskTest expected;
1791 expected.mutable_single_mask()->add_paths("path.to.map[\"key1\"]");
1792 expected.mutable_single_mask()->add_paths(
1793 "path.to.map[\"e\\\"[]][scape\\\"\"]");
1794 expected.mutable_single_mask()->add_paths("path.to.map[\"key2\"]");
1795
1796 ow_->StartObject("");
1797 ow_->RenderString("single_mask",
1798 "path.to.map[\"key1\"],path.to.map[\"e\\\"[]][scape\\\"\"],"
1799 "path.to.map[\"key2\"]");
1800 ow_->EndObject();
1801
1802 CheckOutput(expected);
1803}
1804
1805TEST_P(ProtoStreamObjectWriterFieldMaskTest,
1806 MapKeyMustBeAtTheEndOfAPathSegment) {
1807 EXPECT_CALL(
1808 listener_,
Feng Xiaoeee38b02015-08-22 18:25:48 -07001809 InvalidValue(
1810 _, StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
1811 StringPiece("Field 'single_mask', Invalid FieldMask "
1812 "'path.to.map[\"key1\"]a,path.to.map[\"key2\"]'. "
1813 "Map keys should be at the end of a path segment.")));
Feng Xiaoe96ff302015-06-15 18:21:48 -07001814
1815 ow_->StartObject("");
1816 ow_->RenderString("single_mask",
1817 "path.to.map[\"key1\"]a,path.to.map[\"key2\"]");
1818 ow_->EndObject();
1819}
1820
1821TEST_P(ProtoStreamObjectWriterFieldMaskTest, MapKeyMustEnd) {
1822 EXPECT_CALL(
1823 listener_,
1824 InvalidValue(_,
1825 StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
Feng Xiaoeee38b02015-08-22 18:25:48 -07001826 StringPiece("Field 'single_mask', Invalid FieldMask "
1827 "'path.to.map[\"key1\"'. Map keys should be "
1828 "represented as [\"some_key\"].")));
Feng Xiaoe96ff302015-06-15 18:21:48 -07001829
1830 ow_->StartObject("");
1831 ow_->RenderString("single_mask", "path.to.map[\"key1\"");
1832 ow_->EndObject();
1833}
1834
1835TEST_P(ProtoStreamObjectWriterFieldMaskTest, MapKeyMustBeEscapedCorrectly) {
1836 EXPECT_CALL(
1837 listener_,
1838 InvalidValue(_,
1839 StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
Feng Xiaoeee38b02015-08-22 18:25:48 -07001840 StringPiece("Field 'single_mask', Invalid FieldMask "
1841 "'path.to.map[\"ke\"y1\"]'. Map keys should be "
1842 "represented as [\"some_key\"].")));
Feng Xiaoe96ff302015-06-15 18:21:48 -07001843
1844 ow_->StartObject("");
1845 ow_->RenderString("single_mask", "path.to.map[\"ke\"y1\"]");
1846 ow_->EndObject();
1847}
1848
1849TEST_P(ProtoStreamObjectWriterFieldMaskTest, MapKeyCanContainAnyChars) {
1850 FieldMaskTest expected;
1851 expected.mutable_single_mask()->add_paths(
Feng Xiao17347e32015-12-30 01:18:22 -08001852 // \xE5\xAD\x99 is the UTF-8 byte sequence for chinese character å­™.
1853 // We cannot embed non-ASCII characters in the code directly because
1854 // some windows compilers will try to interpret them using the system's
1855 // current encoding and end up with invalid UTF-8 byte sequence.
1856 "path.to.map[\"(),[],\\\"'!@#$%^&*123_|War\xE5\xAD\x99,./?><\\\\\"]");
Feng Xiaoe96ff302015-06-15 18:21:48 -07001857 expected.mutable_single_mask()->add_paths("path.to.map[\"key2\"]");
1858
1859 ow_->StartObject("");
1860 ow_->RenderString(
1861 "single_mask",
Feng Xiao17347e32015-12-30 01:18:22 -08001862 "path.to.map[\"(),[],\\\"'!@#$%^&*123_|War\xE5\xAD\x99,./?><\\\\\"],"
Feng Xiaoe96ff302015-06-15 18:21:48 -07001863 "path.to.map[\"key2\"]");
1864 ow_->EndObject();
1865
1866 CheckOutput(expected);
1867}
1868
Feng Xiaoeee38b02015-08-22 18:25:48 -07001869class ProtoStreamObjectWriterOneOfsTest
1870 : public BaseProtoStreamObjectWriterTest {
1871 protected:
1872 ProtoStreamObjectWriterOneOfsTest() {
1873 vector<const Descriptor*> descriptors;
1874 descriptors.push_back(OneOfsRequest::descriptor());
1875 descriptors.push_back(google::protobuf::Struct::descriptor());
1876 ResetTypeInfo(descriptors);
1877 }
1878};
1879
1880INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
1881 ProtoStreamObjectWriterOneOfsTest,
1882 ::testing::Values(
1883 testing::USE_TYPE_RESOLVER));
1884
1885TEST_P(ProtoStreamObjectWriterOneOfsTest,
1886 MultipleOneofsFailForPrimitiveTypesTest) {
1887 EXPECT_CALL(
1888 listener_,
1889 InvalidValue(
1890 _, StringPiece("oneof"),
1891 StringPiece(
1892 "oneof field 'data' is already set. Cannot set 'intData'")));
1893
1894 ow_->StartObject("");
1895 ow_->RenderString("strData", "blah");
1896 ow_->RenderString("intData", "123");
1897 ow_->EndObject();
1898}
1899
1900TEST_P(ProtoStreamObjectWriterOneOfsTest,
1901 MultipleOneofsFailForMessageTypesPrimitiveFirstTest) {
1902 // Test for setting primitive oneof field first and then message field.
1903 EXPECT_CALL(listener_,
1904 InvalidValue(_, StringPiece("oneof"),
1905 StringPiece("oneof field 'data' is already set. "
1906 "Cannot set 'messageData'")));
1907
1908 // JSON: { "strData": "blah", "messageData": { "dataValue": 123 } }
1909 ow_->StartObject("");
1910 ow_->RenderString("strData", "blah");
1911 ow_->StartObject("messageData");
1912 ow_->RenderInt32("dataValue", 123);
1913 ow_->EndObject();
1914 ow_->EndObject();
1915}
1916
1917TEST_P(ProtoStreamObjectWriterOneOfsTest,
1918 MultipleOneofsFailForMessageTypesMessageFirstTest) {
1919 // Test for setting message oneof field first and then primitive field.
1920 EXPECT_CALL(listener_,
1921 InvalidValue(_, StringPiece("oneof"),
1922 StringPiece("oneof field 'data' is already set. "
1923 "Cannot set 'strData'")));
1924
1925 // JSON: { "messageData": { "dataValue": 123 }, "strData": "blah" }
1926 ow_->StartObject("");
1927 ow_->StartObject("messageData");
1928 ow_->RenderInt32("dataValue", 123);
1929 ow_->EndObject();
1930 ow_->RenderString("strData", "blah");
1931 ow_->EndObject();
1932}
1933
1934TEST_P(ProtoStreamObjectWriterOneOfsTest,
1935 MultipleOneofsFailForStructTypesPrimitiveFirstTest) {
1936 EXPECT_CALL(listener_,
1937 InvalidValue(_, StringPiece("oneof"),
1938 StringPiece("oneof field 'data' is already set. "
1939 "Cannot set 'structData'")));
1940
1941 // JSON: { "strData": "blah", "structData": { "a": "b" } }
1942 ow_->StartObject("");
1943 ow_->RenderString("strData", "blah");
1944 ow_->StartObject("structData");
1945 ow_->RenderString("a", "b");
1946 ow_->EndObject();
1947 ow_->EndObject();
1948}
1949
1950TEST_P(ProtoStreamObjectWriterOneOfsTest,
1951 MultipleOneofsFailForStructTypesStructFirstTest) {
1952 EXPECT_CALL(listener_,
1953 InvalidValue(_, StringPiece("oneof"),
1954 StringPiece("oneof field 'data' is already set. "
1955 "Cannot set 'strData'")));
1956
1957 // JSON: { "structData": { "a": "b" }, "strData": "blah" }
1958 ow_->StartObject("");
1959 ow_->StartObject("structData");
1960 ow_->RenderString("a", "b");
1961 ow_->EndObject();
1962 ow_->RenderString("strData", "blah");
1963 ow_->EndObject();
1964}
1965
1966TEST_P(ProtoStreamObjectWriterOneOfsTest,
1967 MultipleOneofsFailForStructValueTypesTest) {
1968 EXPECT_CALL(listener_,
1969 InvalidValue(_, StringPiece("oneof"),
1970 StringPiece("oneof field 'data' is already set. "
1971 "Cannot set 'valueData'")));
1972
1973 // JSON: { "messageData": { "dataValue": 123 }, "valueData": { "a": "b" } }
1974 ow_->StartObject("");
1975 ow_->StartObject("messageData");
1976 ow_->RenderInt32("dataValue", 123);
1977 ow_->EndObject();
1978 ow_->StartObject("valueData");
1979 ow_->RenderString("a", "b");
1980 ow_->EndObject();
1981 ow_->EndObject();
1982}
1983
1984TEST_P(ProtoStreamObjectWriterOneOfsTest,
1985 MultipleOneofsFailForWellKnownTypesPrimitiveFirstTest) {
1986 EXPECT_CALL(listener_,
1987 InvalidValue(_, StringPiece("oneof"),
1988 StringPiece("oneof field 'data' is already set. "
1989 "Cannot set 'tsData'")));
1990
1991 // JSON: { "intData": 123, "tsData": "1970-01-02T01:00:00.000Z" }
1992 ow_->StartObject("");
1993 ow_->RenderInt32("intData", 123);
1994 ow_->RenderString("tsData", "1970-01-02T01:00:00.000Z");
1995 ow_->EndObject();
1996}
1997
1998TEST_P(ProtoStreamObjectWriterOneOfsTest,
1999 MultipleOneofsFailForWellKnownTypesWktFirstTest) {
2000 EXPECT_CALL(listener_,
2001 InvalidValue(_, StringPiece("oneof"),
2002 StringPiece("oneof field 'data' is already set. "
2003 "Cannot set 'intData'")));
2004
2005 // JSON: { "tsData": "1970-01-02T01:00:00.000Z", "intData": 123 }
2006 ow_->StartObject("");
2007 ow_->RenderString("tsData", "1970-01-02T01:00:00.000Z");
2008 ow_->RenderInt32("intData", 123);
2009 ow_->EndObject();
2010}
2011
2012TEST_P(ProtoStreamObjectWriterOneOfsTest,
2013 MultipleOneofsFailForWellKnownTypesAndMessageTest) {
2014 EXPECT_CALL(listener_,
2015 InvalidValue(_, StringPiece("oneof"),
2016 StringPiece("oneof field 'data' is already set. "
2017 "Cannot set 'messageData'")));
2018
2019 // JSON: { "tsData": "1970-01-02T01:00:00.000Z",
2020 // "messageData": { "dataValue": 123 } }
2021 ow_->StartObject("");
2022 ow_->RenderString("tsData", "1970-01-02T01:00:00.000Z");
2023 ow_->StartObject("messageData");
2024 ow_->RenderInt32("dataValue", 123);
2025 ow_->EndObject();
2026 ow_->EndObject();
2027}
2028
2029TEST_P(ProtoStreamObjectWriterOneOfsTest,
2030 MultipleOneofsFailForOneofWithinAnyTest) {
2031 EXPECT_CALL(listener_,
2032 InvalidValue(_, StringPiece("oneof"),
2033 StringPiece("oneof field 'data' is already set. "
2034 "Cannot set 'intData'")));
2035
2036 using google::protobuf::testing::oneofs::OneOfsRequest;
2037 // JSON:
2038 // { "anyData":
2039 // { "@type":
2040 // "type.googleapis.com/google.protobuf.testing.oneofs.OneOfsRequest",
2041 // "strData": "blah",
2042 // "intData": 123
2043 // }
2044 // }
2045 ow_->StartObject("");
2046 ow_->StartObject("anyData");
2047 ow_->RenderString(
2048 "@type",
2049 "type.googleapis.com/google.protobuf.testing.oneofs.OneOfsRequest");
2050 ow_->RenderString("strData", "blah");
2051 ow_->RenderInt32("intData", 123);
2052 ow_->EndObject();
Jisi Liu46e8ff62015-10-05 11:59:43 -07002053 ow_->EndObject();
Feng Xiaoeee38b02015-08-22 18:25:48 -07002054}
2055
Feng Xiaoe96ff302015-06-15 18:21:48 -07002056} // namespace converter
2057} // namespace util
2058} // namespace protobuf
2059} // namespace google