Home | History | Annotate | Download | only in internal
      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_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 <google/protobuf/util/internal/testdata/timestamp_duration.pb.h>
     54 #include <gtest/gtest.h>
     55 
     56 
     57 namespace google {
     58 namespace protobuf {
     59 namespace util {
     60 namespace converter {
     61 
     62 using google::protobuf::Descriptor;
     63 using google::protobuf::DescriptorPool;
     64 using google::protobuf::FileDescriptorProto;
     65 using google::protobuf::Message;
     66 using google::protobuf::io::ArrayInputStream;
     67 using google::protobuf::io::CodedInputStream;
     68 using util::Status;
     69 using google::protobuf::testing::Author;
     70 using google::protobuf::testing::BadAuthor;
     71 using google::protobuf::testing::BadNestedBook;
     72 using google::protobuf::testing::Book;
     73 using google::protobuf::testing::Cyclic;
     74 using google::protobuf::testing::Book_Label;
     75 using google::protobuf::testing::NestedBook;
     76 using google::protobuf::testing::PackedPrimitive;
     77 using google::protobuf::testing::Primitive;
     78 using google::protobuf::testing::more_author;
     79 using google::protobuf::testing::maps::MapOut;
     80 using google::protobuf::testing::maps::MapOutWireFormat;
     81 using google::protobuf::testing::timestampduration::TimestampDuration;
     82 using google::protobuf::testing::anys::AnyOut;
     83 using google::protobuf::testing::anys::AnyM;
     84 using google::protobuf::testing::FieldMaskTest;
     85 using google::protobuf::testing::NestedFieldMask;
     86 using google::protobuf::testing::structs::StructType;
     87 using ::testing::_;
     88 
     89 
     90 namespace {
     91 string GetTypeUrl(const Descriptor* descriptor) {
     92   return string(kTypeServiceBaseUrl) + "/" + descriptor->full_name();
     93 }
     94 }  // namespace
     95 
     96 class ProtostreamObjectSourceTest
     97     : public ::testing::TestWithParam<testing::TypeInfoSource> {
     98  protected:
     99   ProtostreamObjectSourceTest()
    100       : helper_(GetParam()),
    101         mock_(),
    102         ow_(&mock_),
    103         use_lower_camel_for_enums_(false) {
    104     helper_.ResetTypeInfo(Book::descriptor());
    105   }
    106 
    107   virtual ~ProtostreamObjectSourceTest() {}
    108 
    109   void DoTest(const Message& msg, const Descriptor* descriptor) {
    110     Status status = ExecuteTest(msg, descriptor);
    111     EXPECT_EQ(Status::OK, status);
    112   }
    113 
    114   Status ExecuteTest(const Message& msg, const Descriptor* descriptor) {
    115     ostringstream oss;
    116     msg.SerializePartialToOstream(&oss);
    117     string proto = oss.str();
    118     ArrayInputStream arr_stream(proto.data(), proto.size());
    119     CodedInputStream in_stream(&arr_stream);
    120 
    121     google::protobuf::scoped_ptr<ProtoStreamObjectSource> os(
    122         helper_.NewProtoSource(&in_stream, GetTypeUrl(descriptor)));
    123     if (use_lower_camel_for_enums_) os->set_use_lower_camel_for_enums(true);
    124     os->set_max_recursion_depth(64);
    125     return os->WriteTo(&mock_);
    126   }
    127 
    128   void PrepareExpectingObjectWriterForRepeatedPrimitive() {
    129     ow_.StartObject("")
    130         ->StartList("repFix32")
    131         ->RenderUint32("", bit_cast<uint32>(3201))
    132         ->RenderUint32("", bit_cast<uint32>(0))
    133         ->RenderUint32("", bit_cast<uint32>(3202))
    134         ->EndList()
    135         ->StartList("repU32")
    136         ->RenderUint32("", bit_cast<uint32>(3203))
    137         ->RenderUint32("", bit_cast<uint32>(0))
    138         ->EndList()
    139         ->StartList("repI32")
    140         ->RenderInt32("", 0)
    141         ->RenderInt32("", 3204)
    142         ->RenderInt32("", 3205)
    143         ->EndList()
    144         ->StartList("repSf32")
    145         ->RenderInt32("", 3206)
    146         ->RenderInt32("", 0)
    147         ->EndList()
    148         ->StartList("repS32")
    149         ->RenderInt32("", 0)
    150         ->RenderInt32("", 3207)
    151         ->RenderInt32("", 3208)
    152         ->EndList()
    153         ->StartList("repFix64")
    154         ->RenderUint64("", bit_cast<uint64>(6401LL))
    155         ->RenderUint64("", bit_cast<uint64>(0LL))
    156         ->EndList()
    157         ->StartList("repU64")
    158         ->RenderUint64("", bit_cast<uint64>(0LL))
    159         ->RenderUint64("", bit_cast<uint64>(6402LL))
    160         ->RenderUint64("", bit_cast<uint64>(6403LL))
    161         ->EndList()
    162         ->StartList("repI64")
    163         ->RenderInt64("", 6404L)
    164         ->RenderInt64("", 0L)
    165         ->EndList()
    166         ->StartList("repSf64")
    167         ->RenderInt64("", 0L)
    168         ->RenderInt64("", 6405L)
    169         ->RenderInt64("", 6406L)
    170         ->EndList()
    171         ->StartList("repS64")
    172         ->RenderInt64("", 6407L)
    173         ->RenderInt64("", 0L)
    174         ->EndList()
    175         ->StartList("repFloat")
    176         ->RenderFloat("", 0.0f)
    177         ->RenderFloat("", 32.1f)
    178         ->RenderFloat("", 32.2f)
    179         ->EndList()
    180         ->StartList("repDouble")
    181         ->RenderDouble("", 64.1L)
    182         ->RenderDouble("", 0.0L)
    183         ->EndList()
    184         ->StartList("repBool")
    185         ->RenderBool("", true)
    186         ->RenderBool("", false)
    187         ->EndList()
    188         ->EndObject();
    189   }
    190 
    191   Primitive PrepareRepeatedPrimitive() {
    192     Primitive primitive;
    193     primitive.add_rep_fix32(3201);
    194     primitive.add_rep_fix32(0);
    195     primitive.add_rep_fix32(3202);
    196     primitive.add_rep_u32(3203);
    197     primitive.add_rep_u32(0);
    198     primitive.add_rep_i32(0);
    199     primitive.add_rep_i32(3204);
    200     primitive.add_rep_i32(3205);
    201     primitive.add_rep_sf32(3206);
    202     primitive.add_rep_sf32(0);
    203     primitive.add_rep_s32(0);
    204     primitive.add_rep_s32(3207);
    205     primitive.add_rep_s32(3208);
    206     primitive.add_rep_fix64(6401L);
    207     primitive.add_rep_fix64(0L);
    208     primitive.add_rep_u64(0L);
    209     primitive.add_rep_u64(6402L);
    210     primitive.add_rep_u64(6403L);
    211     primitive.add_rep_i64(6404L);
    212     primitive.add_rep_i64(0L);
    213     primitive.add_rep_sf64(0L);
    214     primitive.add_rep_sf64(6405L);
    215     primitive.add_rep_sf64(6406L);
    216     primitive.add_rep_s64(6407L);
    217     primitive.add_rep_s64(0L);
    218     primitive.add_rep_float(0.0f);
    219     primitive.add_rep_float(32.1f);
    220     primitive.add_rep_float(32.2f);
    221     primitive.add_rep_double(64.1L);
    222     primitive.add_rep_double(0.0);
    223     primitive.add_rep_bool(true);
    224     primitive.add_rep_bool(false);
    225 
    226     PrepareExpectingObjectWriterForRepeatedPrimitive();
    227     return primitive;
    228   }
    229 
    230   PackedPrimitive PreparePackedPrimitive() {
    231     PackedPrimitive primitive;
    232     primitive.add_rep_fix32(3201);
    233     primitive.add_rep_fix32(0);
    234     primitive.add_rep_fix32(3202);
    235     primitive.add_rep_u32(3203);
    236     primitive.add_rep_u32(0);
    237     primitive.add_rep_i32(0);
    238     primitive.add_rep_i32(3204);
    239     primitive.add_rep_i32(3205);
    240     primitive.add_rep_sf32(3206);
    241     primitive.add_rep_sf32(0);
    242     primitive.add_rep_s32(0);
    243     primitive.add_rep_s32(3207);
    244     primitive.add_rep_s32(3208);
    245     primitive.add_rep_fix64(6401L);
    246     primitive.add_rep_fix64(0L);
    247     primitive.add_rep_u64(0L);
    248     primitive.add_rep_u64(6402L);
    249     primitive.add_rep_u64(6403L);
    250     primitive.add_rep_i64(6404L);
    251     primitive.add_rep_i64(0L);
    252     primitive.add_rep_sf64(0L);
    253     primitive.add_rep_sf64(6405L);
    254     primitive.add_rep_sf64(6406L);
    255     primitive.add_rep_s64(6407L);
    256     primitive.add_rep_s64(0L);
    257     primitive.add_rep_float(0.0f);
    258     primitive.add_rep_float(32.1f);
    259     primitive.add_rep_float(32.2f);
    260     primitive.add_rep_double(64.1L);
    261     primitive.add_rep_double(0.0);
    262     primitive.add_rep_bool(true);
    263     primitive.add_rep_bool(false);
    264 
    265     PrepareExpectingObjectWriterForRepeatedPrimitive();
    266     return primitive;
    267   }
    268 
    269   void UseLowerCamelForEnums() { use_lower_camel_for_enums_ = true; }
    270 
    271   testing::TypeInfoTestHelper helper_;
    272 
    273   ::testing::NiceMock<MockObjectWriter> mock_;
    274   ExpectingObjectWriter ow_;
    275   bool use_lower_camel_for_enums_;
    276 };
    277 
    278 INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
    279                         ProtostreamObjectSourceTest,
    280                         ::testing::Values(
    281                             testing::USE_TYPE_RESOLVER));
    282 
    283 TEST_P(ProtostreamObjectSourceTest, EmptyMessage) {
    284   Book empty;
    285   ow_.StartObject("")->EndObject();
    286   DoTest(empty, Book::descriptor());
    287 }
    288 
    289 TEST_P(ProtostreamObjectSourceTest, Primitives) {
    290   Primitive primitive;
    291   primitive.set_fix32(3201);
    292   primitive.set_u32(3202);
    293   primitive.set_i32(3203);
    294   primitive.set_sf32(3204);
    295   primitive.set_s32(3205);
    296   primitive.set_fix64(6401L);
    297   primitive.set_u64(6402L);
    298   primitive.set_i64(6403L);
    299   primitive.set_sf64(6404L);
    300   primitive.set_s64(6405L);
    301   primitive.set_str("String Value");
    302   primitive.set_bytes("Some Bytes");
    303   primitive.set_float_(32.1f);
    304   primitive.set_double_(64.1L);
    305   primitive.set_bool_(true);
    306 
    307   ow_.StartObject("")
    308       ->RenderUint32("fix32", bit_cast<uint32>(3201))
    309       ->RenderUint32("u32", bit_cast<uint32>(3202))
    310       ->RenderInt32("i32", 3203)
    311       ->RenderInt32("sf32", 3204)
    312       ->RenderInt32("s32", 3205)
    313       ->RenderUint64("fix64", bit_cast<uint64>(6401LL))
    314       ->RenderUint64("u64", bit_cast<uint64>(6402LL))
    315       ->RenderInt64("i64", 6403L)
    316       ->RenderInt64("sf64", 6404L)
    317       ->RenderInt64("s64", 6405L)
    318       ->RenderString("str", "String Value")
    319       ->RenderBytes("bytes", "Some Bytes")
    320       ->RenderFloat("float", 32.1f)
    321       ->RenderDouble("double", 64.1L)
    322       ->RenderBool("bool", true)
    323       ->EndObject();
    324   DoTest(primitive, Primitive::descriptor());
    325 }
    326 
    327 TEST_P(ProtostreamObjectSourceTest, RepeatingPrimitives) {
    328   Primitive primitive = PrepareRepeatedPrimitive();
    329   primitive.add_rep_str("String One");
    330   primitive.add_rep_str("String Two");
    331   primitive.add_rep_bytes("Some Bytes");
    332 
    333   ow_.StartList("repStr")
    334       ->RenderString("", "String One")
    335       ->RenderString("", "String Two")
    336       ->EndList()
    337       ->StartList("repBytes")
    338       ->RenderBytes("", "Some Bytes")
    339       ->EndList();
    340   DoTest(primitive, Primitive::descriptor());
    341 }
    342 
    343 TEST_P(ProtostreamObjectSourceTest, CustomJsonName) {
    344   Author author;
    345   author.set_id(12345);
    346 
    347   ow_.StartObject("")->RenderUint64("@id", 12345)->EndObject();
    348   DoTest(author, Author::descriptor());
    349 }
    350 
    351 TEST_P(ProtostreamObjectSourceTest, NestedMessage) {
    352   Author* author = new Author();
    353   author->set_name("Tolstoy");
    354   Book book;
    355   book.set_title("My Book");
    356   book.set_allocated_author(author);
    357 
    358   ow_.StartObject("")
    359       ->RenderString("title", "My Book")
    360       ->StartObject("author")
    361       ->RenderString("name", "Tolstoy")
    362       ->EndObject()
    363       ->EndObject();
    364   DoTest(book, Book::descriptor());
    365 }
    366 
    367 TEST_P(ProtostreamObjectSourceTest, RepeatingField) {
    368   Author author;
    369   author.set_alive(false);
    370   author.set_name("john");
    371   author.add_pseudonym("phil");
    372   author.add_pseudonym("bob");
    373 
    374   ow_.StartObject("")
    375       ->RenderBool("alive", false)
    376       ->RenderString("name", "john")
    377       ->StartList("pseudonym")
    378       ->RenderString("", "phil")
    379       ->RenderString("", "bob")
    380       ->EndList()
    381       ->EndObject();
    382   DoTest(author, Author::descriptor());
    383 }
    384 
    385 TEST_P(ProtostreamObjectSourceTest, PackedRepeatingFields) {
    386   DoTest(PreparePackedPrimitive(), PackedPrimitive::descriptor());
    387 }
    388 
    389 TEST_P(ProtostreamObjectSourceTest, NonPackedPackableFieldsActuallyPacked) {
    390   // Protostream is packed, but parse with non-packed Primitive.
    391   DoTest(PreparePackedPrimitive(), Primitive::descriptor());
    392 }
    393 
    394 TEST_P(ProtostreamObjectSourceTest, PackedPackableFieldNotActuallyPacked) {
    395   // Protostream is not packed, but parse with PackedPrimitive.
    396   DoTest(PrepareRepeatedPrimitive(), PackedPrimitive::descriptor());
    397 }
    398 
    399 TEST_P(ProtostreamObjectSourceTest, BadAuthor) {
    400   Author author;
    401   author.set_alive(false);
    402   author.set_name("john");
    403   author.set_id(1234L);
    404   author.add_pseudonym("phil");
    405   author.add_pseudonym("bob");
    406 
    407   ow_.StartObject("")
    408       ->StartList("alive")
    409       ->RenderBool("", false)
    410       ->EndList()
    411       ->StartList("name")
    412       ->RenderUint64("", static_cast<uint64>('j'))
    413       ->RenderUint64("", static_cast<uint64>('o'))
    414       ->RenderUint64("", static_cast<uint64>('h'))
    415       ->RenderUint64("", static_cast<uint64>('n'))
    416       ->EndList()
    417       ->RenderString("pseudonym", "phil")
    418       ->RenderString("pseudonym", "bob")
    419       ->EndObject();
    420   // Protostream created with Author, but parsed with BadAuthor.
    421   DoTest(author, BadAuthor::descriptor());
    422 }
    423 
    424 TEST_P(ProtostreamObjectSourceTest, NestedBookToBadNestedBook) {
    425   Book* book = new Book();
    426   book->set_length(250);
    427   book->set_published(2014L);
    428   NestedBook nested;
    429   nested.set_allocated_book(book);
    430 
    431   ow_.StartObject("")
    432       ->StartList("book")
    433       ->RenderUint32("", 24)  // tag for field length (3 << 3)
    434       ->RenderUint32("", 250)
    435       ->RenderUint32("", 32)  // tag for field published (4 << 3)
    436       ->RenderUint32("", 2014)
    437       ->EndList()
    438       ->EndObject();
    439   // Protostream created with NestedBook, but parsed with BadNestedBook.
    440   DoTest(nested, BadNestedBook::descriptor());
    441 }
    442 
    443 TEST_P(ProtostreamObjectSourceTest, BadNestedBookToNestedBook) {
    444   BadNestedBook nested;
    445   nested.add_book(1);
    446   nested.add_book(2);
    447   nested.add_book(3);
    448   nested.add_book(4);
    449   nested.add_book(5);
    450   nested.add_book(6);
    451   nested.add_book(7);
    452 
    453   ow_.StartObject("")->StartObject("book")->EndObject()->EndObject();
    454   // Protostream created with BadNestedBook, but parsed with NestedBook.
    455   DoTest(nested, NestedBook::descriptor());
    456 }
    457 
    458 TEST_P(ProtostreamObjectSourceTest,
    459        LongRepeatedListDoesNotBreakIntoMultipleJsonLists) {
    460   Book book;
    461 
    462   int repeat = 10000;
    463   for (int i = 0; i < repeat; ++i) {
    464     Book_Label* label = book.add_labels();
    465     label->set_key(StrCat("i", i));
    466     label->set_value(StrCat("v", i));
    467   }
    468 
    469   // Make sure StartList and EndList are called exactly once (see b/18227499 for
    470   // problems when this doesn't happen)
    471   EXPECT_CALL(mock_, StartList(_)).Times(1);
    472   EXPECT_CALL(mock_, EndList()).Times(1);
    473 
    474   DoTest(book, Book::descriptor());
    475 }
    476 
    477 TEST_P(ProtostreamObjectSourceTest, LowerCamelEnumOutputTest) {
    478   Book book;
    479   book.set_type(Book::ACTION_AND_ADVENTURE);
    480 
    481   UseLowerCamelForEnums();
    482 
    483   ow_.StartObject("")->RenderString("type", "actionAndAdventure")->EndObject();
    484   DoTest(book, Book::descriptor());
    485 }
    486 
    487 TEST_P(ProtostreamObjectSourceTest, EnumCaseIsUnchangedByDefault) {
    488   Book book;
    489   book.set_type(Book::ACTION_AND_ADVENTURE);
    490   ow_.StartObject("")
    491       ->RenderString("type", "ACTION_AND_ADVENTURE")
    492       ->EndObject();
    493   DoTest(book, Book::descriptor());
    494 }
    495 
    496 TEST_P(ProtostreamObjectSourceTest, CyclicMessageDepthTest) {
    497   Cyclic cyclic;
    498   cyclic.set_m_int(123);
    499 
    500   Book* book = cyclic.mutable_m_book();
    501   book->set_title("book title");
    502   Cyclic* current = cyclic.mutable_m_cyclic();
    503   Author* current_author = cyclic.add_m_author();
    504   for (int i = 0; i < 63; ++i) {
    505     Author* next = current_author->add_friend_();
    506     next->set_id(i);
    507     next->set_name(StrCat("author_name_", i));
    508     next->set_alive(true);
    509     current_author = next;
    510   }
    511 
    512   // Recursive message with depth (65) > max (max is 64).
    513   for (int i = 0; i < 64; ++i) {
    514     Cyclic* next = current->mutable_m_cyclic();
    515     next->set_m_str(StrCat("count_", i));
    516     current = next;
    517   }
    518 
    519   Status status = ExecuteTest(cyclic, Cyclic::descriptor());
    520   EXPECT_EQ(util::error::INVALID_ARGUMENT, status.error_code());
    521 }
    522 
    523 class ProtostreamObjectSourceMapsTest : public ProtostreamObjectSourceTest {
    524  protected:
    525   ProtostreamObjectSourceMapsTest() {
    526     helper_.ResetTypeInfo(MapOut::descriptor());
    527   }
    528 };
    529 
    530 INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
    531                         ProtostreamObjectSourceMapsTest,
    532                         ::testing::Values(
    533                             testing::USE_TYPE_RESOLVER));
    534 
    535 // Tests JSON map.
    536 //
    537 // This is the example expected output.
    538 // {
    539 //   "map1": {
    540 //     "key1": {
    541 //       "foo": "foovalue"
    542 //     },
    543 //     "key2": {
    544 //       "foo": "barvalue"
    545 //     }
    546 //   },
    547 //   "map2": {
    548 //     "nestedself": {
    549 //       "map1": {
    550 //         "nested_key1": {
    551 //           "foo": "nested_foo"
    552 //         }
    553 //       },
    554 //       "bar": "nested_bar_string"
    555 //     }
    556 //   },
    557 //   "map3": {
    558 //     "111": "one one one"
    559 //   },
    560 //   "bar": "top bar"
    561 // }
    562 TEST_P(ProtostreamObjectSourceMapsTest, MapsTest) {
    563   MapOut out;
    564   (*out.mutable_map1())["key1"].set_foo("foovalue");
    565   (*out.mutable_map1())["key2"].set_foo("barvalue");
    566 
    567   MapOut* nested_value = &(*out.mutable_map2())["nestedself"];
    568   (*nested_value->mutable_map1())["nested_key1"].set_foo("nested_foo");
    569   nested_value->set_bar("nested_bar_string");
    570 
    571   (*out.mutable_map3())[111] = "one one one";
    572 
    573   out.set_bar("top bar");
    574 
    575   ow_.StartObject("")
    576       ->StartObject("map1")
    577       ->StartObject("key1")
    578       ->RenderString("foo", "foovalue")
    579       ->EndObject()
    580       ->StartObject("key2")
    581       ->RenderString("foo", "barvalue")
    582       ->EndObject()
    583       ->StartObject("map2")
    584       ->StartObject("nestedself")
    585       ->StartObject("map1")
    586       ->StartObject("nested_key1")
    587       ->RenderString("foo", "nested_foo")
    588       ->EndObject()
    589       ->EndObject()
    590       ->RenderString("bar", "nested_bar_string")
    591       ->EndObject()
    592       ->EndObject()
    593       ->StartObject("map3")
    594       ->RenderString("111", "one one one")
    595       ->EndObject()
    596       ->EndObject()
    597       ->RenderString("bar", "top bar")
    598       ->EndObject();
    599 
    600   DoTest(out, MapOut::descriptor());
    601 }
    602 
    603 TEST_P(ProtostreamObjectSourceMapsTest, MissingKeysTest) {
    604   // MapOutWireFormat has the same wire representation with MapOut but uses
    605   // repeated message fields to represent map fields so we can intentionally
    606   // leave out the key field or the value field of a map entry.
    607   MapOutWireFormat out;
    608   // Create some map entries without keys. They will be rendered with the
    609   // default values ("" for strings, "0" for integers, etc.).
    610   // {
    611   //   "map1": {
    612   //     "": {
    613   //       "foo": "foovalue"
    614   //     }
    615   //   },
    616   //   "map2": {
    617   //     "": {
    618   //       "map1": {
    619   //         "nested_key1": {
    620   //           "foo": "nested_foo"
    621   //         }
    622   //       }
    623   //     }
    624   //   },
    625   //   "map3": {
    626   //     "0": "one one one"
    627   //   },
    628   //   "map4": {
    629   //     "false": "bool"
    630   //   }
    631   // }
    632   out.add_map1()->mutable_value()->set_foo("foovalue");
    633   MapOut* nested = out.add_map2()->mutable_value();
    634   (*nested->mutable_map1())["nested_key1"].set_foo("nested_foo");
    635   out.add_map3()->set_value("one one one");
    636   out.add_map4()->set_value("bool");
    637 
    638   ow_.StartObject("")
    639       ->StartObject("map1")
    640       ->StartObject("")
    641       ->RenderString("foo", "foovalue")
    642       ->EndObject()
    643       ->EndObject()
    644       ->StartObject("map2")
    645       ->StartObject("")
    646       ->StartObject("map1")
    647       ->StartObject("nested_key1")
    648       ->RenderString("foo", "nested_foo")
    649       ->EndObject()
    650       ->EndObject()
    651       ->EndObject()
    652       ->EndObject()
    653       ->StartObject("map3")
    654       ->RenderString("0", "one one one")
    655       ->EndObject()
    656       ->StartObject("map4")
    657       ->RenderString("false", "bool")
    658       ->EndObject()
    659       ->EndObject();
    660 
    661   DoTest(out, MapOut::descriptor());
    662 }
    663 
    664 class ProtostreamObjectSourceAnysTest : public ProtostreamObjectSourceTest {
    665  protected:
    666   ProtostreamObjectSourceAnysTest() {
    667     helper_.ResetTypeInfo(AnyOut::descriptor(),
    668                           google::protobuf::Any::descriptor());
    669   }
    670 };
    671 
    672 INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
    673                         ProtostreamObjectSourceAnysTest,
    674                         ::testing::Values(
    675                             testing::USE_TYPE_RESOLVER));
    676 
    677 // Tests JSON any support.
    678 //
    679 // This is the example expected output.
    680 // {
    681 //   "any": {
    682 //     "@type": "type.googleapis.com/google.protobuf.testing.anys.AnyM"
    683 //     "foo": "foovalue"
    684 //   }
    685 // }
    686 TEST_P(ProtostreamObjectSourceAnysTest, BasicAny) {
    687   AnyOut out;
    688   ::google::protobuf::Any* any = out.mutable_any();
    689 
    690   AnyM m;
    691   m.set_foo("foovalue");
    692   any->PackFrom(m);
    693 
    694   ow_.StartObject("")
    695       ->StartObject("any")
    696       ->RenderString("@type",
    697                      "type.googleapis.com/google.protobuf.testing.anys.AnyM")
    698       ->RenderString("foo", "foovalue")
    699       ->EndObject()
    700       ->EndObject();
    701 
    702   DoTest(out, AnyOut::descriptor());
    703 }
    704 
    705 TEST_P(ProtostreamObjectSourceAnysTest, RecursiveAny) {
    706   AnyOut out;
    707   ::google::protobuf::Any* any = out.mutable_any();
    708   any->set_type_url("type.googleapis.com/google.protobuf.Any");
    709 
    710   ::google::protobuf::Any nested_any;
    711   nested_any.set_type_url(
    712       "type.googleapis.com/google.protobuf.testing.anys.AnyM");
    713 
    714   AnyM m;
    715   m.set_foo("foovalue");
    716   nested_any.set_value(m.SerializeAsString());
    717 
    718   any->set_value(nested_any.SerializeAsString());
    719 
    720   ow_.StartObject("")
    721       ->StartObject("any")
    722       ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
    723       ->StartObject("value")
    724       ->RenderString("@type",
    725                      "type.googleapis.com/google.protobuf.testing.anys.AnyM")
    726       ->RenderString("foo", "foovalue")
    727       ->EndObject()
    728       ->EndObject()
    729       ->EndObject();
    730 
    731   DoTest(out, AnyOut::descriptor());
    732 }
    733 
    734 TEST_P(ProtostreamObjectSourceAnysTest, DoubleRecursiveAny) {
    735   AnyOut out;
    736   ::google::protobuf::Any* any = out.mutable_any();
    737   any->set_type_url("type.googleapis.com/google.protobuf.Any");
    738 
    739   ::google::protobuf::Any nested_any;
    740   nested_any.set_type_url("type.googleapis.com/google.protobuf.Any");
    741 
    742   ::google::protobuf::Any second_nested_any;
    743   second_nested_any.set_type_url(
    744       "type.googleapis.com/google.protobuf.testing.anys.AnyM");
    745 
    746   AnyM m;
    747   m.set_foo("foovalue");
    748   second_nested_any.set_value(m.SerializeAsString());
    749   nested_any.set_value(second_nested_any.SerializeAsString());
    750   any->set_value(nested_any.SerializeAsString());
    751 
    752   ow_.StartObject("")
    753       ->StartObject("any")
    754       ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
    755       ->StartObject("value")
    756       ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
    757       ->StartObject("value")
    758       ->RenderString("@type",
    759                      "type.googleapis.com/google.protobuf.testing.anys.AnyM")
    760       ->RenderString("foo", "foovalue")
    761       ->EndObject()
    762       ->EndObject()
    763       ->EndObject()
    764       ->EndObject();
    765 
    766   DoTest(out, AnyOut::descriptor());
    767 }
    768 
    769 TEST_P(ProtostreamObjectSourceAnysTest, EmptyAnyOutputsEmptyObject) {
    770   AnyOut out;
    771   out.mutable_any();
    772 
    773   ow_.StartObject("")->StartObject("any")->EndObject()->EndObject();
    774 
    775   DoTest(out, AnyOut::descriptor());
    776 }
    777 
    778 TEST_P(ProtostreamObjectSourceAnysTest, EmptyWithTypeAndNoValueOutputsType) {
    779   AnyOut out;
    780   out.mutable_any()->set_type_url("foo.googleapis.com/my.Type");
    781 
    782   ow_.StartObject("")
    783       ->StartObject("any")
    784       ->RenderString("@type", "foo.googleapis.com/my.Type")
    785       ->EndObject()
    786       ->EndObject();
    787 
    788   DoTest(out, AnyOut::descriptor());
    789 }
    790 
    791 TEST_P(ProtostreamObjectSourceAnysTest, MissingTypeUrlError) {
    792   AnyOut out;
    793   ::google::protobuf::Any* any = out.mutable_any();
    794 
    795   AnyM m;
    796   m.set_foo("foovalue");
    797   any->set_value(m.SerializeAsString());
    798 
    799   // We start the "AnyOut" part and then fail when we hit the Any object.
    800   ow_.StartObject("");
    801 
    802   Status status = ExecuteTest(out, AnyOut::descriptor());
    803   EXPECT_EQ(util::error::INTERNAL, status.error_code());
    804 }
    805 
    806 TEST_P(ProtostreamObjectSourceAnysTest, UnknownTypeServiceError) {
    807   AnyOut out;
    808   ::google::protobuf::Any* any = out.mutable_any();
    809   any->set_type_url("foo.googleapis.com/my.own.Type");
    810 
    811   AnyM m;
    812   m.set_foo("foovalue");
    813   any->set_value(m.SerializeAsString());
    814 
    815   // We start the "AnyOut" part and then fail when we hit the Any object.
    816   ow_.StartObject("");
    817 
    818   Status status = ExecuteTest(out, AnyOut::descriptor());
    819   EXPECT_EQ(util::error::INTERNAL, status.error_code());
    820 }
    821 
    822 TEST_P(ProtostreamObjectSourceAnysTest, UnknownTypeError) {
    823   AnyOut out;
    824   ::google::protobuf::Any* any = out.mutable_any();
    825   any->set_type_url("type.googleapis.com/unknown.Type");
    826 
    827   AnyM m;
    828   m.set_foo("foovalue");
    829   any->set_value(m.SerializeAsString());
    830 
    831   // We start the "AnyOut" part and then fail when we hit the Any object.
    832   ow_.StartObject("");
    833 
    834   Status status = ExecuteTest(out, AnyOut::descriptor());
    835   EXPECT_EQ(util::error::INTERNAL, status.error_code());
    836 }
    837 
    838 class ProtostreamObjectSourceStructTest : public ProtostreamObjectSourceTest {
    839  protected:
    840   ProtostreamObjectSourceStructTest() {
    841     helper_.ResetTypeInfo(StructType::descriptor(),
    842                           google::protobuf::Struct::descriptor());
    843   }
    844 };
    845 
    846 INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
    847                         ProtostreamObjectSourceStructTest,
    848                         ::testing::Values(
    849                             testing::USE_TYPE_RESOLVER));
    850 
    851 // Tests struct
    852 //
    853 //  "object": {
    854 //    "k1": 123,
    855 //    "k2": true
    856 //  }
    857 TEST_P(ProtostreamObjectSourceStructTest, StructRenderSuccess) {
    858   StructType out;
    859   google::protobuf::Struct* s = out.mutable_object();
    860   s->mutable_fields()->operator[]("k1").set_number_value(123);
    861   s->mutable_fields()->operator[]("k2").set_bool_value(true);
    862 
    863   ow_.StartObject("")
    864       ->StartObject("object")
    865       ->RenderDouble("k1", 123)
    866       ->RenderBool("k2", true)
    867       ->EndObject()
    868       ->EndObject();
    869 
    870   DoTest(out, StructType::descriptor());
    871 }
    872 
    873 TEST_P(ProtostreamObjectSourceStructTest, MissingValueSkipsField) {
    874   StructType out;
    875   google::protobuf::Struct* s = out.mutable_object();
    876   s->mutable_fields()->operator[]("k1");
    877 
    878   ow_.StartObject("")->StartObject("object")->EndObject()->EndObject();
    879 
    880   DoTest(out, StructType::descriptor());
    881 }
    882 
    883 class ProtostreamObjectSourceFieldMaskTest
    884     : public ProtostreamObjectSourceTest {
    885  protected:
    886   ProtostreamObjectSourceFieldMaskTest() {
    887     helper_.ResetTypeInfo(FieldMaskTest::descriptor(),
    888                           google::protobuf::FieldMask::descriptor());
    889   }
    890 };
    891 
    892 INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
    893                         ProtostreamObjectSourceFieldMaskTest,
    894                         ::testing::Values(
    895                             testing::USE_TYPE_RESOLVER));
    896 
    897 TEST_P(ProtostreamObjectSourceFieldMaskTest, FieldMaskRenderSuccess) {
    898   FieldMaskTest out;
    899   out.set_id("1");
    900   out.mutable_single_mask()->add_paths("path1");
    901   out.mutable_single_mask()->add_paths("snake_case_path2");
    902   ::google::protobuf::FieldMask* mask = out.add_repeated_mask();
    903   mask->add_paths("path3");
    904   mask = out.add_repeated_mask();
    905   mask->add_paths("snake_case_path4");
    906   mask->add_paths("path5");
    907   NestedFieldMask* nested = out.add_nested_mask();
    908   nested->set_data("data");
    909   nested->mutable_single_mask()->add_paths("nested.path1");
    910   nested->mutable_single_mask()->add_paths("nested_field.snake_case_path2");
    911   mask = nested->add_repeated_mask();
    912   mask->add_paths("nested_field.path3");
    913   mask->add_paths("nested.snake_case_path4");
    914   mask = nested->add_repeated_mask();
    915   mask->add_paths("nested.path5");
    916   mask = nested->add_repeated_mask();
    917   mask->add_paths(
    918       "snake_case.map_field[\"map_key_should_be_ignored\"].nested_snake_case."
    919       "map_field[\"map_key_sho\\\"uld_be_ignored\"]");
    920 
    921   ow_.StartObject("")
    922       ->RenderString("id", "1")
    923       ->RenderString("singleMask", "path1,snakeCasePath2")
    924       ->StartList("repeatedMask")
    925       ->RenderString("", "path3")
    926       ->RenderString("", "snakeCasePath4,path5")
    927       ->EndList()
    928       ->StartList("nestedMask")
    929       ->StartObject("")
    930       ->RenderString("data", "data")
    931       ->RenderString("singleMask", "nested.path1,nestedField.snakeCasePath2")
    932       ->StartList("repeatedMask")
    933       ->RenderString("", "nestedField.path3,nested.snakeCasePath4")
    934       ->RenderString("", "nested.path5")
    935       ->RenderString("",
    936                      "snakeCase.mapField[\"map_key_should_be_ignored\"]."
    937                      "nestedSnakeCase.mapField[\"map_key_sho\\\"uld_be_"
    938                      "ignored\"]")
    939       ->EndList()
    940       ->EndObject()
    941       ->EndList()
    942       ->EndObject();
    943 
    944   DoTest(out, FieldMaskTest::descriptor());
    945 }
    946 
    947 class ProtostreamObjectSourceTimestampTest
    948     : public ProtostreamObjectSourceTest {
    949  protected:
    950   ProtostreamObjectSourceTimestampTest() {
    951     helper_.ResetTypeInfo(TimestampDuration::descriptor());
    952   }
    953 };
    954 
    955 INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
    956                         ProtostreamObjectSourceTimestampTest,
    957                         ::testing::Values(
    958                             testing::USE_TYPE_RESOLVER));
    959 
    960 TEST_P(ProtostreamObjectSourceTimestampTest, InvalidTimestampBelowMinTest) {
    961   TimestampDuration out;
    962   google::protobuf::Timestamp* ts = out.mutable_ts();
    963   // Min allowed seconds - 1
    964   ts->set_seconds(kTimestampMinSeconds - 1);
    965   ow_.StartObject("");
    966 
    967   Status status = ExecuteTest(out, TimestampDuration::descriptor());
    968   EXPECT_EQ(util::error::INTERNAL, status.error_code());
    969 }
    970 
    971 TEST_P(ProtostreamObjectSourceTimestampTest, InvalidTimestampAboveMaxTest) {
    972   TimestampDuration out;
    973   google::protobuf::Timestamp* ts = out.mutable_ts();
    974   // Max allowed seconds + 1
    975   ts->set_seconds(kTimestampMaxSeconds + 1);
    976   ow_.StartObject("");
    977 
    978   Status status = ExecuteTest(out, TimestampDuration::descriptor());
    979   EXPECT_EQ(util::error::INTERNAL, status.error_code());
    980 }
    981 
    982 TEST_P(ProtostreamObjectSourceTimestampTest, InvalidDurationBelowMinTest) {
    983   TimestampDuration out;
    984   google::protobuf::Duration* dur = out.mutable_dur();
    985   // Min allowed seconds - 1
    986   dur->set_seconds(kDurationMinSeconds - 1);
    987   ow_.StartObject("");
    988 
    989   Status status = ExecuteTest(out, TimestampDuration::descriptor());
    990   EXPECT_EQ(util::error::INTERNAL, status.error_code());
    991 }
    992 
    993 TEST_P(ProtostreamObjectSourceTimestampTest, InvalidDurationAboveMaxTest) {
    994   TimestampDuration out;
    995   google::protobuf::Duration* dur = out.mutable_dur();
    996   // Min allowed seconds + 1
    997   dur->set_seconds(kDurationMaxSeconds + 1);
    998   ow_.StartObject("");
    999 
   1000   Status status = ExecuteTest(out, TimestampDuration::descriptor());
   1001   EXPECT_EQ(util::error::INTERNAL, status.error_code());
   1002 }
   1003 
   1004 }  // namespace converter
   1005 }  // namespace util
   1006 }  // namespace protobuf
   1007 }  // namespace google
   1008