blob: 561f67634e78f181751f859b17b157cc5283dc87 [file] [log] [blame]
Feng Xiaoe96ff302015-06-15 18:21:48 -07001// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc. All rights reserved.
3// https://developers.google.com/protocol-buffers/
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9// * Redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer.
11// * Redistributions in binary form must reproduce the above
12// copyright notice, this list of conditions and the following disclaimer
13// in the documentation and/or other materials provided with the
14// distribution.
15// * Neither the name of Google Inc. nor the names of its
16// contributors may be used to endorse or promote products derived from
17// this software without specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31#include <google/protobuf/util/internal/protostream_objectsource.h>
32
33#include <memory>
34#ifndef _SHARED_PTR_H
35#include <google/protobuf/stubs/shared_ptr.h>
36#endif
37#include <sstream>
38
39#include <google/protobuf/stubs/casts.h>
40#include <google/protobuf/any.pb.h>
41#include <google/protobuf/io/coded_stream.h>
42#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
43#include <google/protobuf/descriptor.h>
44#include <google/protobuf/util/internal/expecting_objectwriter.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/type_info_test_helper.h>
48#include <google/protobuf/util/internal/constants.h>
49#include <google/protobuf/stubs/strutil.h>
50#include <google/protobuf/util/internal/testdata/anys.pb.h>
51#include <google/protobuf/util/internal/testdata/maps.pb.h>
52#include <google/protobuf/util/internal/testdata/struct.pb.h>
53#include <gtest/gtest.h>
54
55
56namespace google {
57namespace protobuf {
58namespace util {
59namespace converter {
60
61using google::protobuf::Descriptor;
62using google::protobuf::DescriptorPool;
63using google::protobuf::FileDescriptorProto;
64using google::protobuf::Message;
65using google::protobuf::io::ArrayInputStream;
66using google::protobuf::io::CodedInputStream;
67using util::Status;
68using google::protobuf::testing::Author;
69using google::protobuf::testing::BadAuthor;
70using google::protobuf::testing::BadNestedBook;
71using google::protobuf::testing::Book;
72using google::protobuf::testing::Book_Label;
73using google::protobuf::testing::NestedBook;
74using google::protobuf::testing::PackedPrimitive;
75using google::protobuf::testing::Primitive;
76using google::protobuf::testing::more_author;
77using google::protobuf::testing::maps::MapOut;
78using google::protobuf::testing::anys::AnyOut;
79using google::protobuf::testing::anys::AnyM;
80using google::protobuf::testing::FieldMaskTest;
81using google::protobuf::testing::NestedFieldMask;
82using google::protobuf::testing::structs::StructType;
83using ::testing::_;
84
85
86namespace {
87string GetTypeUrl(const Descriptor* descriptor) {
88 return string(kTypeServiceBaseUrl) + "/" + descriptor->full_name();
89}
90} // namespace
91
92class ProtostreamObjectSourceTest
93 : public ::testing::TestWithParam<testing::TypeInfoSource> {
94 protected:
95 ProtostreamObjectSourceTest() : helper_(GetParam()), mock_(), ow_(&mock_) {
96 helper_.ResetTypeInfo(Book::descriptor());
97 }
98
99 virtual ~ProtostreamObjectSourceTest() {}
100
101 void DoTest(const Message& msg, const Descriptor* descriptor) {
102 Status status = ExecuteTest(msg, descriptor);
103 EXPECT_EQ(Status::OK, status);
104 }
105
106 Status ExecuteTest(const Message& msg, const Descriptor* descriptor) {
107 ostringstream oss;
108 msg.SerializePartialToOstream(&oss);
109 string proto = oss.str();
110 ArrayInputStream arr_stream(proto.data(), proto.size());
111 CodedInputStream in_stream(&arr_stream);
112
113 google::protobuf::scoped_ptr<ProtoStreamObjectSource> os(
114 helper_.NewProtoSource(&in_stream, GetTypeUrl(descriptor)));
115 return os->WriteTo(&mock_);
116 }
117
118 void PrepareExpectingObjectWriterForRepeatedPrimitive() {
119 ow_.StartObject("")
Feng Xiaoeee38b02015-08-22 18:25:48 -0700120 ->StartList("repFix32")
Feng Xiaoe96ff302015-06-15 18:21:48 -0700121 ->RenderUint32("", bit_cast<uint32>(3201))
122 ->RenderUint32("", bit_cast<uint32>(0))
123 ->RenderUint32("", bit_cast<uint32>(3202))
124 ->EndList()
Feng Xiaoeee38b02015-08-22 18:25:48 -0700125 ->StartList("repU32")
Feng Xiaoe96ff302015-06-15 18:21:48 -0700126 ->RenderUint32("", bit_cast<uint32>(3203))
127 ->RenderUint32("", bit_cast<uint32>(0))
128 ->EndList()
Feng Xiaoeee38b02015-08-22 18:25:48 -0700129 ->StartList("repI32")
Feng Xiaoe96ff302015-06-15 18:21:48 -0700130 ->RenderInt32("", 0)
131 ->RenderInt32("", 3204)
132 ->RenderInt32("", 3205)
133 ->EndList()
Feng Xiaoeee38b02015-08-22 18:25:48 -0700134 ->StartList("repSf32")
Feng Xiaoe96ff302015-06-15 18:21:48 -0700135 ->RenderInt32("", 3206)
136 ->RenderInt32("", 0)
137 ->EndList()
Feng Xiaoeee38b02015-08-22 18:25:48 -0700138 ->StartList("repS32")
Feng Xiaoe96ff302015-06-15 18:21:48 -0700139 ->RenderInt32("", 0)
140 ->RenderInt32("", 3207)
141 ->RenderInt32("", 3208)
142 ->EndList()
Feng Xiaoeee38b02015-08-22 18:25:48 -0700143 ->StartList("repFix64")
Feng Xiao818c5ee2015-06-15 21:42:57 -0700144 ->RenderUint64("", bit_cast<uint64>(6401LL))
145 ->RenderUint64("", bit_cast<uint64>(0LL))
Feng Xiaoe96ff302015-06-15 18:21:48 -0700146 ->EndList()
Feng Xiaoeee38b02015-08-22 18:25:48 -0700147 ->StartList("repU64")
Feng Xiao818c5ee2015-06-15 21:42:57 -0700148 ->RenderUint64("", bit_cast<uint64>(0LL))
149 ->RenderUint64("", bit_cast<uint64>(6402LL))
150 ->RenderUint64("", bit_cast<uint64>(6403LL))
Feng Xiaoe96ff302015-06-15 18:21:48 -0700151 ->EndList()
Feng Xiaoeee38b02015-08-22 18:25:48 -0700152 ->StartList("repI64")
Feng Xiaoe96ff302015-06-15 18:21:48 -0700153 ->RenderInt64("", 6404L)
154 ->RenderInt64("", 0L)
155 ->EndList()
Feng Xiaoeee38b02015-08-22 18:25:48 -0700156 ->StartList("repSf64")
Feng Xiaoe96ff302015-06-15 18:21:48 -0700157 ->RenderInt64("", 0L)
158 ->RenderInt64("", 6405L)
159 ->RenderInt64("", 6406L)
160 ->EndList()
Feng Xiaoeee38b02015-08-22 18:25:48 -0700161 ->StartList("repS64")
Feng Xiaoe96ff302015-06-15 18:21:48 -0700162 ->RenderInt64("", 6407L)
163 ->RenderInt64("", 0L)
164 ->EndList()
Feng Xiaoeee38b02015-08-22 18:25:48 -0700165 ->StartList("repFloat")
Feng Xiaoe96ff302015-06-15 18:21:48 -0700166 ->RenderFloat("", 0.0f)
167 ->RenderFloat("", 32.1f)
168 ->RenderFloat("", 32.2f)
169 ->EndList()
Feng Xiaoeee38b02015-08-22 18:25:48 -0700170 ->StartList("repDouble")
Feng Xiaoe96ff302015-06-15 18:21:48 -0700171 ->RenderDouble("", 64.1L)
172 ->RenderDouble("", 0.0L)
173 ->EndList()
Feng Xiaoeee38b02015-08-22 18:25:48 -0700174 ->StartList("repBool")
Feng Xiaoe96ff302015-06-15 18:21:48 -0700175 ->RenderBool("", true)
176 ->RenderBool("", false)
177 ->EndList()
178 ->EndObject();
179 }
180
181 Primitive PrepareRepeatedPrimitive() {
182 Primitive primitive;
183 primitive.add_rep_fix32(3201);
184 primitive.add_rep_fix32(0);
185 primitive.add_rep_fix32(3202);
186 primitive.add_rep_u32(3203);
187 primitive.add_rep_u32(0);
188 primitive.add_rep_i32(0);
189 primitive.add_rep_i32(3204);
190 primitive.add_rep_i32(3205);
191 primitive.add_rep_sf32(3206);
192 primitive.add_rep_sf32(0);
193 primitive.add_rep_s32(0);
194 primitive.add_rep_s32(3207);
195 primitive.add_rep_s32(3208);
196 primitive.add_rep_fix64(6401L);
197 primitive.add_rep_fix64(0L);
198 primitive.add_rep_u64(0L);
199 primitive.add_rep_u64(6402L);
200 primitive.add_rep_u64(6403L);
201 primitive.add_rep_i64(6404L);
202 primitive.add_rep_i64(0L);
203 primitive.add_rep_sf64(0L);
204 primitive.add_rep_sf64(6405L);
205 primitive.add_rep_sf64(6406L);
206 primitive.add_rep_s64(6407L);
207 primitive.add_rep_s64(0L);
208 primitive.add_rep_float(0.0f);
209 primitive.add_rep_float(32.1f);
210 primitive.add_rep_float(32.2f);
211 primitive.add_rep_double(64.1L);
212 primitive.add_rep_double(0.0);
213 primitive.add_rep_bool(true);
214 primitive.add_rep_bool(false);
215
216 PrepareExpectingObjectWriterForRepeatedPrimitive();
217 return primitive;
218 }
219
220 PackedPrimitive PreparePackedPrimitive() {
221 PackedPrimitive primitive;
222 primitive.add_rep_fix32(3201);
223 primitive.add_rep_fix32(0);
224 primitive.add_rep_fix32(3202);
225 primitive.add_rep_u32(3203);
226 primitive.add_rep_u32(0);
227 primitive.add_rep_i32(0);
228 primitive.add_rep_i32(3204);
229 primitive.add_rep_i32(3205);
230 primitive.add_rep_sf32(3206);
231 primitive.add_rep_sf32(0);
232 primitive.add_rep_s32(0);
233 primitive.add_rep_s32(3207);
234 primitive.add_rep_s32(3208);
235 primitive.add_rep_fix64(6401L);
236 primitive.add_rep_fix64(0L);
237 primitive.add_rep_u64(0L);
238 primitive.add_rep_u64(6402L);
239 primitive.add_rep_u64(6403L);
240 primitive.add_rep_i64(6404L);
241 primitive.add_rep_i64(0L);
242 primitive.add_rep_sf64(0L);
243 primitive.add_rep_sf64(6405L);
244 primitive.add_rep_sf64(6406L);
245 primitive.add_rep_s64(6407L);
246 primitive.add_rep_s64(0L);
247 primitive.add_rep_float(0.0f);
248 primitive.add_rep_float(32.1f);
249 primitive.add_rep_float(32.2f);
250 primitive.add_rep_double(64.1L);
251 primitive.add_rep_double(0.0);
252 primitive.add_rep_bool(true);
253 primitive.add_rep_bool(false);
254
255 PrepareExpectingObjectWriterForRepeatedPrimitive();
256 return primitive;
257 }
258
259 testing::TypeInfoTestHelper helper_;
260
261 ::testing::NiceMock<MockObjectWriter> mock_;
262 ExpectingObjectWriter ow_;
263};
264
265INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
266 ProtostreamObjectSourceTest,
267 ::testing::Values(
268 testing::USE_TYPE_RESOLVER));
269
270TEST_P(ProtostreamObjectSourceTest, EmptyMessage) {
271 Book empty;
272 ow_.StartObject("")->EndObject();
273 DoTest(empty, Book::descriptor());
274}
275
276TEST_P(ProtostreamObjectSourceTest, Primitives) {
277 Primitive primitive;
278 primitive.set_fix32(3201);
279 primitive.set_u32(3202);
280 primitive.set_i32(3203);
281 primitive.set_sf32(3204);
282 primitive.set_s32(3205);
283 primitive.set_fix64(6401L);
284 primitive.set_u64(6402L);
285 primitive.set_i64(6403L);
286 primitive.set_sf64(6404L);
287 primitive.set_s64(6405L);
288 primitive.set_str("String Value");
289 primitive.set_bytes("Some Bytes");
290 primitive.set_float_(32.1f);
291 primitive.set_double_(64.1L);
292 primitive.set_bool_(true);
293
294 ow_.StartObject("")
295 ->RenderUint32("fix32", bit_cast<uint32>(3201))
296 ->RenderUint32("u32", bit_cast<uint32>(3202))
297 ->RenderInt32("i32", 3203)
298 ->RenderInt32("sf32", 3204)
299 ->RenderInt32("s32", 3205)
Feng Xiao818c5ee2015-06-15 21:42:57 -0700300 ->RenderUint64("fix64", bit_cast<uint64>(6401LL))
301 ->RenderUint64("u64", bit_cast<uint64>(6402LL))
Feng Xiaoe96ff302015-06-15 18:21:48 -0700302 ->RenderInt64("i64", 6403L)
303 ->RenderInt64("sf64", 6404L)
304 ->RenderInt64("s64", 6405L)
305 ->RenderString("str", "String Value")
306 ->RenderBytes("bytes", "Some Bytes")
307 ->RenderFloat("float", 32.1f)
308 ->RenderDouble("double", 64.1L)
309 ->RenderBool("bool", true)
310 ->EndObject();
311 DoTest(primitive, Primitive::descriptor());
312}
313
314TEST_P(ProtostreamObjectSourceTest, RepeatingPrimitives) {
315 Primitive primitive = PrepareRepeatedPrimitive();
316 primitive.add_rep_str("String One");
317 primitive.add_rep_str("String Two");
318 primitive.add_rep_bytes("Some Bytes");
319
Feng Xiaoeee38b02015-08-22 18:25:48 -0700320 ow_.StartList("repStr")
Feng Xiaoe96ff302015-06-15 18:21:48 -0700321 ->RenderString("", "String One")
322 ->RenderString("", "String Two")
323 ->EndList()
Feng Xiaoeee38b02015-08-22 18:25:48 -0700324 ->StartList("repBytes")
Feng Xiaoe96ff302015-06-15 18:21:48 -0700325 ->RenderBytes("", "Some Bytes")
326 ->EndList();
327 DoTest(primitive, Primitive::descriptor());
328}
329
Feng Xiaoe841bac2015-12-11 17:09:20 -0800330TEST_P(ProtostreamObjectSourceTest, CustomJsonName) {
331 Author author;
332 author.set_id(12345);
333
334 ow_.StartObject("")->RenderUint64("@id", 12345)->EndObject();
335 DoTest(author, Author::descriptor());
336}
337
Feng Xiaoe96ff302015-06-15 18:21:48 -0700338TEST_P(ProtostreamObjectSourceTest, NestedMessage) {
339 Author* author = new Author();
Feng Xiaoe96ff302015-06-15 18:21:48 -0700340 author->set_name("Tolstoy");
341 Book book;
342 book.set_title("My Book");
343 book.set_allocated_author(author);
344
345 ow_.StartObject("")
346 ->RenderString("title", "My Book")
347 ->StartObject("author")
Feng Xiaoe96ff302015-06-15 18:21:48 -0700348 ->RenderString("name", "Tolstoy")
349 ->EndObject()
350 ->EndObject();
351 DoTest(book, Book::descriptor());
352}
353
354TEST_P(ProtostreamObjectSourceTest, RepeatingField) {
355 Author author;
356 author.set_alive(false);
357 author.set_name("john");
358 author.add_pseudonym("phil");
359 author.add_pseudonym("bob");
360
361 ow_.StartObject("")
362 ->RenderBool("alive", false)
363 ->RenderString("name", "john")
364 ->StartList("pseudonym")
365 ->RenderString("", "phil")
366 ->RenderString("", "bob")
367 ->EndList()
368 ->EndObject();
369 DoTest(author, Author::descriptor());
370}
371
372TEST_P(ProtostreamObjectSourceTest, PackedRepeatingFields) {
373 DoTest(PreparePackedPrimitive(), PackedPrimitive::descriptor());
374}
375
376TEST_P(ProtostreamObjectSourceTest, NonPackedPackableFieldsActuallyPacked) {
377 // Protostream is packed, but parse with non-packed Primitive.
378 DoTest(PreparePackedPrimitive(), Primitive::descriptor());
379}
380
381TEST_P(ProtostreamObjectSourceTest, PackedPackableFieldNotActuallyPacked) {
382 // Protostream is not packed, but parse with PackedPrimitive.
383 DoTest(PrepareRepeatedPrimitive(), PackedPrimitive::descriptor());
384}
385
386TEST_P(ProtostreamObjectSourceTest, BadAuthor) {
387 Author author;
388 author.set_alive(false);
389 author.set_name("john");
390 author.set_id(1234L);
391 author.add_pseudonym("phil");
392 author.add_pseudonym("bob");
393
394 ow_.StartObject("")
395 ->StartList("alive")
396 ->RenderBool("", false)
397 ->EndList()
398 ->StartList("name")
399 ->RenderUint64("", static_cast<uint64>('j'))
400 ->RenderUint64("", static_cast<uint64>('o'))
401 ->RenderUint64("", static_cast<uint64>('h'))
402 ->RenderUint64("", static_cast<uint64>('n'))
403 ->EndList()
404 ->RenderString("pseudonym", "phil")
405 ->RenderString("pseudonym", "bob")
406 ->EndObject();
407 // Protostream created with Author, but parsed with BadAuthor.
408 DoTest(author, BadAuthor::descriptor());
409}
410
411TEST_P(ProtostreamObjectSourceTest, NestedBookToBadNestedBook) {
412 Book* book = new Book();
413 book->set_length(250);
414 book->set_published(2014L);
415 NestedBook nested;
416 nested.set_allocated_book(book);
417
418 ow_.StartObject("")
419 ->StartList("book")
420 ->RenderUint32("", 24) // tag for field length (3 << 3)
421 ->RenderUint32("", 250)
422 ->RenderUint32("", 32) // tag for field published (4 << 3)
423 ->RenderUint32("", 2014)
424 ->EndList()
425 ->EndObject();
426 // Protostream created with NestedBook, but parsed with BadNestedBook.
427 DoTest(nested, BadNestedBook::descriptor());
428}
429
430TEST_P(ProtostreamObjectSourceTest, BadNestedBookToNestedBook) {
431 BadNestedBook nested;
432 nested.add_book(1);
433 nested.add_book(2);
434 nested.add_book(3);
435 nested.add_book(4);
436 nested.add_book(5);
437 nested.add_book(6);
438 nested.add_book(7);
439
440 ow_.StartObject("")->StartObject("book")->EndObject()->EndObject();
441 // Protostream created with BadNestedBook, but parsed with NestedBook.
442 DoTest(nested, NestedBook::descriptor());
443}
444
445TEST_P(ProtostreamObjectSourceTest,
446 LongRepeatedListDoesNotBreakIntoMultipleJsonLists) {
447 Book book;
448
449 int repeat = 10000;
450 for (int i = 0; i < repeat; ++i) {
451 Book_Label* label = book.add_labels();
452 label->set_key(StrCat("i", i));
453 label->set_value(StrCat("v", i));
454 }
455
456 // Make sure StartList and EndList are called exactly once (see b/18227499 for
457 // problems when this doesn't happen)
458 EXPECT_CALL(mock_, StartList(_)).Times(1);
459 EXPECT_CALL(mock_, EndList()).Times(1);
460
461 DoTest(book, Book::descriptor());
462}
463
464class ProtostreamObjectSourceMapsTest : public ProtostreamObjectSourceTest {
465 protected:
466 ProtostreamObjectSourceMapsTest() {
467 helper_.ResetTypeInfo(MapOut::descriptor());
468 }
469};
470
471INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
472 ProtostreamObjectSourceMapsTest,
473 ::testing::Values(
474 testing::USE_TYPE_RESOLVER));
475
476// Tests JSON map.
477//
478// This is the example expected output.
479// {
480// "map1": {
481// "key1": {
482// "foo": "foovalue"
483// },
484// "key2": {
485// "foo": "barvalue"
486// }
487// },
488// "map2": {
489// "nestedself": {
490// "map1": {
491// "nested_key1": {
492// "foo": "nested_foo"
493// }
494// },
495// "bar": "nested_bar_string"
496// }
497// },
498// "map3": {
499// "111": "one one one"
500// },
501// "bar": "top bar"
502// }
503TEST_P(ProtostreamObjectSourceMapsTest, MapsTest) {
504 MapOut out;
505 (*out.mutable_map1())["key1"].set_foo("foovalue");
506 (*out.mutable_map1())["key2"].set_foo("barvalue");
507
508 MapOut* nested_value = &(*out.mutable_map2())["nestedself"];
509 (*nested_value->mutable_map1())["nested_key1"].set_foo("nested_foo");
510 nested_value->set_bar("nested_bar_string");
511
512 (*out.mutable_map3())[111] = "one one one";
513
514 out.set_bar("top bar");
515
516 ow_.StartObject("")
517 ->StartObject("map1")
518 ->StartObject("key1")
519 ->RenderString("foo", "foovalue")
520 ->EndObject()
521 ->StartObject("key2")
522 ->RenderString("foo", "barvalue")
523 ->EndObject()
524 ->StartObject("map2")
525 ->StartObject("nestedself")
526 ->StartObject("map1")
527 ->StartObject("nested_key1")
528 ->RenderString("foo", "nested_foo")
529 ->EndObject()
530 ->EndObject()
531 ->RenderString("bar", "nested_bar_string")
532 ->EndObject()
533 ->EndObject()
534 ->StartObject("map3")
535 ->RenderString("111", "one one one")
536 ->EndObject()
537 ->EndObject()
538 ->RenderString("bar", "top bar")
539 ->EndObject();
540
541 DoTest(out, MapOut::descriptor());
542}
543
544class ProtostreamObjectSourceAnysTest : public ProtostreamObjectSourceTest {
545 protected:
546 ProtostreamObjectSourceAnysTest() {
547 helper_.ResetTypeInfo(AnyOut::descriptor(),
548 google::protobuf::Any::descriptor());
549 }
550};
551
552INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
553 ProtostreamObjectSourceAnysTest,
554 ::testing::Values(
555 testing::USE_TYPE_RESOLVER));
556
557// Tests JSON any support.
558//
559// This is the example expected output.
560// {
561// "any": {
562// "@type": "type.googleapis.com/google.protobuf.testing.anys.AnyM"
563// "foo": "foovalue"
564// }
565// }
566TEST_P(ProtostreamObjectSourceAnysTest, BasicAny) {
567 AnyOut out;
568 ::google::protobuf::Any* any = out.mutable_any();
569
570 AnyM m;
571 m.set_foo("foovalue");
572 any->PackFrom(m);
573
574 ow_.StartObject("")
575 ->StartObject("any")
576 ->RenderString("@type",
577 "type.googleapis.com/google.protobuf.testing.anys.AnyM")
578 ->RenderString("foo", "foovalue")
579 ->EndObject()
580 ->EndObject();
581
582 DoTest(out, AnyOut::descriptor());
583}
584
585TEST_P(ProtostreamObjectSourceAnysTest, RecursiveAny) {
586 AnyOut out;
587 ::google::protobuf::Any* any = out.mutable_any();
588 any->set_type_url("type.googleapis.com/google.protobuf.Any");
589
590 ::google::protobuf::Any nested_any;
591 nested_any.set_type_url(
592 "type.googleapis.com/google.protobuf.testing.anys.AnyM");
593
594 AnyM m;
595 m.set_foo("foovalue");
596 nested_any.set_value(m.SerializeAsString());
597
598 any->set_value(nested_any.SerializeAsString());
599
600 ow_.StartObject("")
601 ->StartObject("any")
602 ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
603 ->StartObject("value")
604 ->RenderString("@type",
605 "type.googleapis.com/google.protobuf.testing.anys.AnyM")
606 ->RenderString("foo", "foovalue")
607 ->EndObject()
608 ->EndObject()
609 ->EndObject();
610
611 DoTest(out, AnyOut::descriptor());
612}
613
614TEST_P(ProtostreamObjectSourceAnysTest, DoubleRecursiveAny) {
615 AnyOut out;
616 ::google::protobuf::Any* any = out.mutable_any();
617 any->set_type_url("type.googleapis.com/google.protobuf.Any");
618
619 ::google::protobuf::Any nested_any;
620 nested_any.set_type_url("type.googleapis.com/google.protobuf.Any");
621
622 ::google::protobuf::Any second_nested_any;
623 second_nested_any.set_type_url(
624 "type.googleapis.com/google.protobuf.testing.anys.AnyM");
625
626 AnyM m;
627 m.set_foo("foovalue");
628 second_nested_any.set_value(m.SerializeAsString());
629 nested_any.set_value(second_nested_any.SerializeAsString());
630 any->set_value(nested_any.SerializeAsString());
631
632 ow_.StartObject("")
633 ->StartObject("any")
634 ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
635 ->StartObject("value")
636 ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
637 ->StartObject("value")
638 ->RenderString("@type",
639 "type.googleapis.com/google.protobuf.testing.anys.AnyM")
640 ->RenderString("foo", "foovalue")
641 ->EndObject()
642 ->EndObject()
643 ->EndObject()
644 ->EndObject();
645
646 DoTest(out, AnyOut::descriptor());
647}
648
649TEST_P(ProtostreamObjectSourceAnysTest, EmptyAnyOutputsEmptyObject) {
650 AnyOut out;
651 out.mutable_any();
652
653 ow_.StartObject("")->StartObject("any")->EndObject()->EndObject();
654
655 DoTest(out, AnyOut::descriptor());
656}
657
658TEST_P(ProtostreamObjectSourceAnysTest, EmptyWithTypeAndNoValueOutputsType) {
659 AnyOut out;
660 out.mutable_any()->set_type_url("foo.googleapis.com/my.Type");
661
662 ow_.StartObject("")
663 ->StartObject("any")
664 ->RenderString("@type", "foo.googleapis.com/my.Type")
665 ->EndObject()
666 ->EndObject();
667
668 DoTest(out, AnyOut::descriptor());
669}
670
671TEST_P(ProtostreamObjectSourceAnysTest, MissingTypeUrlError) {
672 AnyOut out;
673 ::google::protobuf::Any* any = out.mutable_any();
674
675 AnyM m;
676 m.set_foo("foovalue");
677 any->set_value(m.SerializeAsString());
678
679 // We start the "AnyOut" part and then fail when we hit the Any object.
680 ow_.StartObject("");
681
682 Status status = ExecuteTest(out, AnyOut::descriptor());
683 EXPECT_EQ(util::error::INTERNAL, status.error_code());
684}
685
686TEST_P(ProtostreamObjectSourceAnysTest, UnknownTypeServiceError) {
687 AnyOut out;
688 ::google::protobuf::Any* any = out.mutable_any();
689 any->set_type_url("foo.googleapis.com/my.own.Type");
690
691 AnyM m;
692 m.set_foo("foovalue");
693 any->set_value(m.SerializeAsString());
694
695 // We start the "AnyOut" part and then fail when we hit the Any object.
696 ow_.StartObject("");
697
698 Status status = ExecuteTest(out, AnyOut::descriptor());
699 EXPECT_EQ(util::error::INTERNAL, status.error_code());
700}
701
702TEST_P(ProtostreamObjectSourceAnysTest, UnknownTypeError) {
703 AnyOut out;
704 ::google::protobuf::Any* any = out.mutable_any();
705 any->set_type_url("type.googleapis.com/unknown.Type");
706
707 AnyM m;
708 m.set_foo("foovalue");
709 any->set_value(m.SerializeAsString());
710
711 // We start the "AnyOut" part and then fail when we hit the Any object.
712 ow_.StartObject("");
713
714 Status status = ExecuteTest(out, AnyOut::descriptor());
715 EXPECT_EQ(util::error::INTERNAL, status.error_code());
716}
717
718class ProtostreamObjectSourceStructTest : public ProtostreamObjectSourceTest {
719 protected:
720 ProtostreamObjectSourceStructTest() {
721 helper_.ResetTypeInfo(StructType::descriptor(),
722 google::protobuf::Struct::descriptor());
723 }
724};
725
726INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
727 ProtostreamObjectSourceStructTest,
728 ::testing::Values(
729 testing::USE_TYPE_RESOLVER));
730
731// Tests struct
732//
733// "object": {
734// "k1": 123,
735// "k2": true
736// }
737TEST_P(ProtostreamObjectSourceStructTest, StructRenderSuccess) {
738 StructType out;
739 google::protobuf::Struct* s = out.mutable_object();
740 s->mutable_fields()->operator[]("k1").set_number_value(123);
741 s->mutable_fields()->operator[]("k2").set_bool_value(true);
742
743 ow_.StartObject("")
744 ->StartObject("object")
745 ->RenderDouble("k1", 123)
746 ->RenderBool("k2", true)
747 ->EndObject()
748 ->EndObject();
749
750 DoTest(out, StructType::descriptor());
751}
752
753TEST_P(ProtostreamObjectSourceStructTest, MissingValueSkipsField) {
754 StructType out;
755 google::protobuf::Struct* s = out.mutable_object();
756 s->mutable_fields()->operator[]("k1");
757
758 ow_.StartObject("")->StartObject("object")->EndObject()->EndObject();
759
760 DoTest(out, StructType::descriptor());
761}
762
763class ProtostreamObjectSourceFieldMaskTest
764 : public ProtostreamObjectSourceTest {
765 protected:
766 ProtostreamObjectSourceFieldMaskTest() {
767 helper_.ResetTypeInfo(FieldMaskTest::descriptor(),
768 google::protobuf::FieldMask::descriptor());
769 }
770};
771
772INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
773 ProtostreamObjectSourceFieldMaskTest,
774 ::testing::Values(
775 testing::USE_TYPE_RESOLVER));
776
777TEST_P(ProtostreamObjectSourceFieldMaskTest, FieldMaskRenderSuccess) {
778 FieldMaskTest out;
779 out.set_id("1");
780 out.mutable_single_mask()->add_paths("path1");
781 out.mutable_single_mask()->add_paths("snake_case_path2");
782 ::google::protobuf::FieldMask* mask = out.add_repeated_mask();
783 mask->add_paths("path3");
784 mask = out.add_repeated_mask();
785 mask->add_paths("snake_case_path4");
786 mask->add_paths("path5");
787 NestedFieldMask* nested = out.add_nested_mask();
788 nested->set_data("data");
789 nested->mutable_single_mask()->add_paths("nested.path1");
790 nested->mutable_single_mask()->add_paths("nested_field.snake_case_path2");
791 mask = nested->add_repeated_mask();
792 mask->add_paths("nested_field.path3");
793 mask->add_paths("nested.snake_case_path4");
794 mask = nested->add_repeated_mask();
795 mask->add_paths("nested.path5");
796 mask = nested->add_repeated_mask();
797 mask->add_paths(
798 "snake_case.map_field[\"map_key_should_be_ignored\"].nested_snake_case."
799 "map_field[\"map_key_sho\\\"uld_be_ignored\"]");
800
801 ow_.StartObject("")
802 ->RenderString("id", "1")
Feng Xiaoeee38b02015-08-22 18:25:48 -0700803 ->RenderString("singleMask", "path1,snakeCasePath2")
804 ->StartList("repeatedMask")
Feng Xiaoe96ff302015-06-15 18:21:48 -0700805 ->RenderString("", "path3")
806 ->RenderString("", "snakeCasePath4,path5")
807 ->EndList()
Feng Xiaoeee38b02015-08-22 18:25:48 -0700808 ->StartList("nestedMask")
Feng Xiaoe96ff302015-06-15 18:21:48 -0700809 ->StartObject("")
810 ->RenderString("data", "data")
Feng Xiaoeee38b02015-08-22 18:25:48 -0700811 ->RenderString("singleMask", "nested.path1,nestedField.snakeCasePath2")
812 ->StartList("repeatedMask")
Feng Xiaoe96ff302015-06-15 18:21:48 -0700813 ->RenderString("", "nestedField.path3,nested.snakeCasePath4")
814 ->RenderString("", "nested.path5")
815 ->RenderString("",
816 "snakeCase.mapField[\"map_key_should_be_ignored\"]."
817 "nestedSnakeCase.mapField[\"map_key_sho\\\"uld_be_"
818 "ignored\"]")
819 ->EndList()
820 ->EndObject()
821 ->EndList()
822 ->EndObject();
823
824 DoTest(out, FieldMaskTest::descriptor());
825}
826
827} // namespace converter
828} // namespace util
829} // namespace protobuf
830} // namespace google