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