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