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