| Index: third_party/protobuf/src/google/protobuf/util/internal/protostream_objectsource_test.cc
|
| diff --git a/third_party/protobuf/src/google/protobuf/util/internal/protostream_objectsource_test.cc b/third_party/protobuf/src/google/protobuf/util/internal/protostream_objectsource_test.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..561f67634e78f181751f859b17b157cc5283dc87
|
| --- /dev/null
|
| +++ b/third_party/protobuf/src/google/protobuf/util/internal/protostream_objectsource_test.cc
|
| @@ -0,0 +1,830 @@
|
| +// Protocol Buffers - Google's data interchange format
|
| +// Copyright 2008 Google Inc. All rights reserved.
|
| +// https://developers.google.com/protocol-buffers/
|
| +//
|
| +// Redistribution and use in source and binary forms, with or without
|
| +// modification, are permitted provided that the following conditions are
|
| +// met:
|
| +//
|
| +// * Redistributions of source code must retain the above copyright
|
| +// notice, this list of conditions and the following disclaimer.
|
| +// * Redistributions in binary form must reproduce the above
|
| +// copyright notice, this list of conditions and the following disclaimer
|
| +// in the documentation and/or other materials provided with the
|
| +// distribution.
|
| +// * Neither the name of Google Inc. nor the names of its
|
| +// contributors may be used to endorse or promote products derived from
|
| +// this software without specific prior written permission.
|
| +//
|
| +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
| +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
| +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
| +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
| +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
| +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
| +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
| +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
| +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
| +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| +
|
| +#include <google/protobuf/util/internal/protostream_objectsource.h>
|
| +
|
| +#include <memory>
|
| +#ifndef _SHARED_PTR_H
|
| +#include <google/protobuf/stubs/shared_ptr.h>
|
| +#endif
|
| +#include <sstream>
|
| +
|
| +#include <google/protobuf/stubs/casts.h>
|
| +#include <google/protobuf/any.pb.h>
|
| +#include <google/protobuf/io/coded_stream.h>
|
| +#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
|
| +#include <google/protobuf/descriptor.h>
|
| +#include <google/protobuf/util/internal/expecting_objectwriter.h>
|
| +#include <google/protobuf/util/internal/testdata/books.pb.h>
|
| +#include <google/protobuf/util/internal/testdata/field_mask.pb.h>
|
| +#include <google/protobuf/util/internal/type_info_test_helper.h>
|
| +#include <google/protobuf/util/internal/constants.h>
|
| +#include <google/protobuf/stubs/strutil.h>
|
| +#include <google/protobuf/util/internal/testdata/anys.pb.h>
|
| +#include <google/protobuf/util/internal/testdata/maps.pb.h>
|
| +#include <google/protobuf/util/internal/testdata/struct.pb.h>
|
| +#include <gtest/gtest.h>
|
| +
|
| +
|
| +namespace google {
|
| +namespace protobuf {
|
| +namespace util {
|
| +namespace converter {
|
| +
|
| +using google::protobuf::Descriptor;
|
| +using google::protobuf::DescriptorPool;
|
| +using google::protobuf::FileDescriptorProto;
|
| +using google::protobuf::Message;
|
| +using google::protobuf::io::ArrayInputStream;
|
| +using google::protobuf::io::CodedInputStream;
|
| +using util::Status;
|
| +using google::protobuf::testing::Author;
|
| +using google::protobuf::testing::BadAuthor;
|
| +using google::protobuf::testing::BadNestedBook;
|
| +using google::protobuf::testing::Book;
|
| +using google::protobuf::testing::Book_Label;
|
| +using google::protobuf::testing::NestedBook;
|
| +using google::protobuf::testing::PackedPrimitive;
|
| +using google::protobuf::testing::Primitive;
|
| +using google::protobuf::testing::more_author;
|
| +using google::protobuf::testing::maps::MapOut;
|
| +using google::protobuf::testing::anys::AnyOut;
|
| +using google::protobuf::testing::anys::AnyM;
|
| +using google::protobuf::testing::FieldMaskTest;
|
| +using google::protobuf::testing::NestedFieldMask;
|
| +using google::protobuf::testing::structs::StructType;
|
| +using ::testing::_;
|
| +
|
| +
|
| +namespace {
|
| +string GetTypeUrl(const Descriptor* descriptor) {
|
| + return string(kTypeServiceBaseUrl) + "/" + descriptor->full_name();
|
| +}
|
| +} // namespace
|
| +
|
| +class ProtostreamObjectSourceTest
|
| + : public ::testing::TestWithParam<testing::TypeInfoSource> {
|
| + protected:
|
| + ProtostreamObjectSourceTest() : helper_(GetParam()), mock_(), ow_(&mock_) {
|
| + helper_.ResetTypeInfo(Book::descriptor());
|
| + }
|
| +
|
| + virtual ~ProtostreamObjectSourceTest() {}
|
| +
|
| + void DoTest(const Message& msg, const Descriptor* descriptor) {
|
| + Status status = ExecuteTest(msg, descriptor);
|
| + EXPECT_EQ(Status::OK, status);
|
| + }
|
| +
|
| + Status ExecuteTest(const Message& msg, const Descriptor* descriptor) {
|
| + ostringstream oss;
|
| + msg.SerializePartialToOstream(&oss);
|
| + string proto = oss.str();
|
| + ArrayInputStream arr_stream(proto.data(), proto.size());
|
| + CodedInputStream in_stream(&arr_stream);
|
| +
|
| + google::protobuf::scoped_ptr<ProtoStreamObjectSource> os(
|
| + helper_.NewProtoSource(&in_stream, GetTypeUrl(descriptor)));
|
| + return os->WriteTo(&mock_);
|
| + }
|
| +
|
| + void PrepareExpectingObjectWriterForRepeatedPrimitive() {
|
| + ow_.StartObject("")
|
| + ->StartList("repFix32")
|
| + ->RenderUint32("", bit_cast<uint32>(3201))
|
| + ->RenderUint32("", bit_cast<uint32>(0))
|
| + ->RenderUint32("", bit_cast<uint32>(3202))
|
| + ->EndList()
|
| + ->StartList("repU32")
|
| + ->RenderUint32("", bit_cast<uint32>(3203))
|
| + ->RenderUint32("", bit_cast<uint32>(0))
|
| + ->EndList()
|
| + ->StartList("repI32")
|
| + ->RenderInt32("", 0)
|
| + ->RenderInt32("", 3204)
|
| + ->RenderInt32("", 3205)
|
| + ->EndList()
|
| + ->StartList("repSf32")
|
| + ->RenderInt32("", 3206)
|
| + ->RenderInt32("", 0)
|
| + ->EndList()
|
| + ->StartList("repS32")
|
| + ->RenderInt32("", 0)
|
| + ->RenderInt32("", 3207)
|
| + ->RenderInt32("", 3208)
|
| + ->EndList()
|
| + ->StartList("repFix64")
|
| + ->RenderUint64("", bit_cast<uint64>(6401LL))
|
| + ->RenderUint64("", bit_cast<uint64>(0LL))
|
| + ->EndList()
|
| + ->StartList("repU64")
|
| + ->RenderUint64("", bit_cast<uint64>(0LL))
|
| + ->RenderUint64("", bit_cast<uint64>(6402LL))
|
| + ->RenderUint64("", bit_cast<uint64>(6403LL))
|
| + ->EndList()
|
| + ->StartList("repI64")
|
| + ->RenderInt64("", 6404L)
|
| + ->RenderInt64("", 0L)
|
| + ->EndList()
|
| + ->StartList("repSf64")
|
| + ->RenderInt64("", 0L)
|
| + ->RenderInt64("", 6405L)
|
| + ->RenderInt64("", 6406L)
|
| + ->EndList()
|
| + ->StartList("repS64")
|
| + ->RenderInt64("", 6407L)
|
| + ->RenderInt64("", 0L)
|
| + ->EndList()
|
| + ->StartList("repFloat")
|
| + ->RenderFloat("", 0.0f)
|
| + ->RenderFloat("", 32.1f)
|
| + ->RenderFloat("", 32.2f)
|
| + ->EndList()
|
| + ->StartList("repDouble")
|
| + ->RenderDouble("", 64.1L)
|
| + ->RenderDouble("", 0.0L)
|
| + ->EndList()
|
| + ->StartList("repBool")
|
| + ->RenderBool("", true)
|
| + ->RenderBool("", false)
|
| + ->EndList()
|
| + ->EndObject();
|
| + }
|
| +
|
| + Primitive PrepareRepeatedPrimitive() {
|
| + Primitive primitive;
|
| + primitive.add_rep_fix32(3201);
|
| + primitive.add_rep_fix32(0);
|
| + primitive.add_rep_fix32(3202);
|
| + primitive.add_rep_u32(3203);
|
| + primitive.add_rep_u32(0);
|
| + primitive.add_rep_i32(0);
|
| + primitive.add_rep_i32(3204);
|
| + primitive.add_rep_i32(3205);
|
| + primitive.add_rep_sf32(3206);
|
| + primitive.add_rep_sf32(0);
|
| + primitive.add_rep_s32(0);
|
| + primitive.add_rep_s32(3207);
|
| + primitive.add_rep_s32(3208);
|
| + primitive.add_rep_fix64(6401L);
|
| + primitive.add_rep_fix64(0L);
|
| + primitive.add_rep_u64(0L);
|
| + primitive.add_rep_u64(6402L);
|
| + primitive.add_rep_u64(6403L);
|
| + primitive.add_rep_i64(6404L);
|
| + primitive.add_rep_i64(0L);
|
| + primitive.add_rep_sf64(0L);
|
| + primitive.add_rep_sf64(6405L);
|
| + primitive.add_rep_sf64(6406L);
|
| + primitive.add_rep_s64(6407L);
|
| + primitive.add_rep_s64(0L);
|
| + primitive.add_rep_float(0.0f);
|
| + primitive.add_rep_float(32.1f);
|
| + primitive.add_rep_float(32.2f);
|
| + primitive.add_rep_double(64.1L);
|
| + primitive.add_rep_double(0.0);
|
| + primitive.add_rep_bool(true);
|
| + primitive.add_rep_bool(false);
|
| +
|
| + PrepareExpectingObjectWriterForRepeatedPrimitive();
|
| + return primitive;
|
| + }
|
| +
|
| + PackedPrimitive PreparePackedPrimitive() {
|
| + PackedPrimitive primitive;
|
| + primitive.add_rep_fix32(3201);
|
| + primitive.add_rep_fix32(0);
|
| + primitive.add_rep_fix32(3202);
|
| + primitive.add_rep_u32(3203);
|
| + primitive.add_rep_u32(0);
|
| + primitive.add_rep_i32(0);
|
| + primitive.add_rep_i32(3204);
|
| + primitive.add_rep_i32(3205);
|
| + primitive.add_rep_sf32(3206);
|
| + primitive.add_rep_sf32(0);
|
| + primitive.add_rep_s32(0);
|
| + primitive.add_rep_s32(3207);
|
| + primitive.add_rep_s32(3208);
|
| + primitive.add_rep_fix64(6401L);
|
| + primitive.add_rep_fix64(0L);
|
| + primitive.add_rep_u64(0L);
|
| + primitive.add_rep_u64(6402L);
|
| + primitive.add_rep_u64(6403L);
|
| + primitive.add_rep_i64(6404L);
|
| + primitive.add_rep_i64(0L);
|
| + primitive.add_rep_sf64(0L);
|
| + primitive.add_rep_sf64(6405L);
|
| + primitive.add_rep_sf64(6406L);
|
| + primitive.add_rep_s64(6407L);
|
| + primitive.add_rep_s64(0L);
|
| + primitive.add_rep_float(0.0f);
|
| + primitive.add_rep_float(32.1f);
|
| + primitive.add_rep_float(32.2f);
|
| + primitive.add_rep_double(64.1L);
|
| + primitive.add_rep_double(0.0);
|
| + primitive.add_rep_bool(true);
|
| + primitive.add_rep_bool(false);
|
| +
|
| + PrepareExpectingObjectWriterForRepeatedPrimitive();
|
| + return primitive;
|
| + }
|
| +
|
| + testing::TypeInfoTestHelper helper_;
|
| +
|
| + ::testing::NiceMock<MockObjectWriter> mock_;
|
| + ExpectingObjectWriter ow_;
|
| +};
|
| +
|
| +INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
|
| + ProtostreamObjectSourceTest,
|
| + ::testing::Values(
|
| + testing::USE_TYPE_RESOLVER));
|
| +
|
| +TEST_P(ProtostreamObjectSourceTest, EmptyMessage) {
|
| + Book empty;
|
| + ow_.StartObject("")->EndObject();
|
| + DoTest(empty, Book::descriptor());
|
| +}
|
| +
|
| +TEST_P(ProtostreamObjectSourceTest, Primitives) {
|
| + Primitive primitive;
|
| + primitive.set_fix32(3201);
|
| + primitive.set_u32(3202);
|
| + primitive.set_i32(3203);
|
| + primitive.set_sf32(3204);
|
| + primitive.set_s32(3205);
|
| + primitive.set_fix64(6401L);
|
| + primitive.set_u64(6402L);
|
| + primitive.set_i64(6403L);
|
| + primitive.set_sf64(6404L);
|
| + primitive.set_s64(6405L);
|
| + primitive.set_str("String Value");
|
| + primitive.set_bytes("Some Bytes");
|
| + primitive.set_float_(32.1f);
|
| + primitive.set_double_(64.1L);
|
| + primitive.set_bool_(true);
|
| +
|
| + ow_.StartObject("")
|
| + ->RenderUint32("fix32", bit_cast<uint32>(3201))
|
| + ->RenderUint32("u32", bit_cast<uint32>(3202))
|
| + ->RenderInt32("i32", 3203)
|
| + ->RenderInt32("sf32", 3204)
|
| + ->RenderInt32("s32", 3205)
|
| + ->RenderUint64("fix64", bit_cast<uint64>(6401LL))
|
| + ->RenderUint64("u64", bit_cast<uint64>(6402LL))
|
| + ->RenderInt64("i64", 6403L)
|
| + ->RenderInt64("sf64", 6404L)
|
| + ->RenderInt64("s64", 6405L)
|
| + ->RenderString("str", "String Value")
|
| + ->RenderBytes("bytes", "Some Bytes")
|
| + ->RenderFloat("float", 32.1f)
|
| + ->RenderDouble("double", 64.1L)
|
| + ->RenderBool("bool", true)
|
| + ->EndObject();
|
| + DoTest(primitive, Primitive::descriptor());
|
| +}
|
| +
|
| +TEST_P(ProtostreamObjectSourceTest, RepeatingPrimitives) {
|
| + Primitive primitive = PrepareRepeatedPrimitive();
|
| + primitive.add_rep_str("String One");
|
| + primitive.add_rep_str("String Two");
|
| + primitive.add_rep_bytes("Some Bytes");
|
| +
|
| + ow_.StartList("repStr")
|
| + ->RenderString("", "String One")
|
| + ->RenderString("", "String Two")
|
| + ->EndList()
|
| + ->StartList("repBytes")
|
| + ->RenderBytes("", "Some Bytes")
|
| + ->EndList();
|
| + DoTest(primitive, Primitive::descriptor());
|
| +}
|
| +
|
| +TEST_P(ProtostreamObjectSourceTest, CustomJsonName) {
|
| + Author author;
|
| + author.set_id(12345);
|
| +
|
| + ow_.StartObject("")->RenderUint64("@id", 12345)->EndObject();
|
| + DoTest(author, Author::descriptor());
|
| +}
|
| +
|
| +TEST_P(ProtostreamObjectSourceTest, NestedMessage) {
|
| + Author* author = new Author();
|
| + author->set_name("Tolstoy");
|
| + Book book;
|
| + book.set_title("My Book");
|
| + book.set_allocated_author(author);
|
| +
|
| + ow_.StartObject("")
|
| + ->RenderString("title", "My Book")
|
| + ->StartObject("author")
|
| + ->RenderString("name", "Tolstoy")
|
| + ->EndObject()
|
| + ->EndObject();
|
| + DoTest(book, Book::descriptor());
|
| +}
|
| +
|
| +TEST_P(ProtostreamObjectSourceTest, RepeatingField) {
|
| + Author author;
|
| + author.set_alive(false);
|
| + author.set_name("john");
|
| + author.add_pseudonym("phil");
|
| + author.add_pseudonym("bob");
|
| +
|
| + ow_.StartObject("")
|
| + ->RenderBool("alive", false)
|
| + ->RenderString("name", "john")
|
| + ->StartList("pseudonym")
|
| + ->RenderString("", "phil")
|
| + ->RenderString("", "bob")
|
| + ->EndList()
|
| + ->EndObject();
|
| + DoTest(author, Author::descriptor());
|
| +}
|
| +
|
| +TEST_P(ProtostreamObjectSourceTest, PackedRepeatingFields) {
|
| + DoTest(PreparePackedPrimitive(), PackedPrimitive::descriptor());
|
| +}
|
| +
|
| +TEST_P(ProtostreamObjectSourceTest, NonPackedPackableFieldsActuallyPacked) {
|
| + // Protostream is packed, but parse with non-packed Primitive.
|
| + DoTest(PreparePackedPrimitive(), Primitive::descriptor());
|
| +}
|
| +
|
| +TEST_P(ProtostreamObjectSourceTest, PackedPackableFieldNotActuallyPacked) {
|
| + // Protostream is not packed, but parse with PackedPrimitive.
|
| + DoTest(PrepareRepeatedPrimitive(), PackedPrimitive::descriptor());
|
| +}
|
| +
|
| +TEST_P(ProtostreamObjectSourceTest, BadAuthor) {
|
| + Author author;
|
| + author.set_alive(false);
|
| + author.set_name("john");
|
| + author.set_id(1234L);
|
| + author.add_pseudonym("phil");
|
| + author.add_pseudonym("bob");
|
| +
|
| + ow_.StartObject("")
|
| + ->StartList("alive")
|
| + ->RenderBool("", false)
|
| + ->EndList()
|
| + ->StartList("name")
|
| + ->RenderUint64("", static_cast<uint64>('j'))
|
| + ->RenderUint64("", static_cast<uint64>('o'))
|
| + ->RenderUint64("", static_cast<uint64>('h'))
|
| + ->RenderUint64("", static_cast<uint64>('n'))
|
| + ->EndList()
|
| + ->RenderString("pseudonym", "phil")
|
| + ->RenderString("pseudonym", "bob")
|
| + ->EndObject();
|
| + // Protostream created with Author, but parsed with BadAuthor.
|
| + DoTest(author, BadAuthor::descriptor());
|
| +}
|
| +
|
| +TEST_P(ProtostreamObjectSourceTest, NestedBookToBadNestedBook) {
|
| + Book* book = new Book();
|
| + book->set_length(250);
|
| + book->set_published(2014L);
|
| + NestedBook nested;
|
| + nested.set_allocated_book(book);
|
| +
|
| + ow_.StartObject("")
|
| + ->StartList("book")
|
| + ->RenderUint32("", 24) // tag for field length (3 << 3)
|
| + ->RenderUint32("", 250)
|
| + ->RenderUint32("", 32) // tag for field published (4 << 3)
|
| + ->RenderUint32("", 2014)
|
| + ->EndList()
|
| + ->EndObject();
|
| + // Protostream created with NestedBook, but parsed with BadNestedBook.
|
| + DoTest(nested, BadNestedBook::descriptor());
|
| +}
|
| +
|
| +TEST_P(ProtostreamObjectSourceTest, BadNestedBookToNestedBook) {
|
| + BadNestedBook nested;
|
| + nested.add_book(1);
|
| + nested.add_book(2);
|
| + nested.add_book(3);
|
| + nested.add_book(4);
|
| + nested.add_book(5);
|
| + nested.add_book(6);
|
| + nested.add_book(7);
|
| +
|
| + ow_.StartObject("")->StartObject("book")->EndObject()->EndObject();
|
| + // Protostream created with BadNestedBook, but parsed with NestedBook.
|
| + DoTest(nested, NestedBook::descriptor());
|
| +}
|
| +
|
| +TEST_P(ProtostreamObjectSourceTest,
|
| + LongRepeatedListDoesNotBreakIntoMultipleJsonLists) {
|
| + Book book;
|
| +
|
| + int repeat = 10000;
|
| + for (int i = 0; i < repeat; ++i) {
|
| + Book_Label* label = book.add_labels();
|
| + label->set_key(StrCat("i", i));
|
| + label->set_value(StrCat("v", i));
|
| + }
|
| +
|
| + // Make sure StartList and EndList are called exactly once (see b/18227499 for
|
| + // problems when this doesn't happen)
|
| + EXPECT_CALL(mock_, StartList(_)).Times(1);
|
| + EXPECT_CALL(mock_, EndList()).Times(1);
|
| +
|
| + DoTest(book, Book::descriptor());
|
| +}
|
| +
|
| +class ProtostreamObjectSourceMapsTest : public ProtostreamObjectSourceTest {
|
| + protected:
|
| + ProtostreamObjectSourceMapsTest() {
|
| + helper_.ResetTypeInfo(MapOut::descriptor());
|
| + }
|
| +};
|
| +
|
| +INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
|
| + ProtostreamObjectSourceMapsTest,
|
| + ::testing::Values(
|
| + testing::USE_TYPE_RESOLVER));
|
| +
|
| +// Tests JSON map.
|
| +//
|
| +// This is the example expected output.
|
| +// {
|
| +// "map1": {
|
| +// "key1": {
|
| +// "foo": "foovalue"
|
| +// },
|
| +// "key2": {
|
| +// "foo": "barvalue"
|
| +// }
|
| +// },
|
| +// "map2": {
|
| +// "nestedself": {
|
| +// "map1": {
|
| +// "nested_key1": {
|
| +// "foo": "nested_foo"
|
| +// }
|
| +// },
|
| +// "bar": "nested_bar_string"
|
| +// }
|
| +// },
|
| +// "map3": {
|
| +// "111": "one one one"
|
| +// },
|
| +// "bar": "top bar"
|
| +// }
|
| +TEST_P(ProtostreamObjectSourceMapsTest, MapsTest) {
|
| + MapOut out;
|
| + (*out.mutable_map1())["key1"].set_foo("foovalue");
|
| + (*out.mutable_map1())["key2"].set_foo("barvalue");
|
| +
|
| + MapOut* nested_value = &(*out.mutable_map2())["nestedself"];
|
| + (*nested_value->mutable_map1())["nested_key1"].set_foo("nested_foo");
|
| + nested_value->set_bar("nested_bar_string");
|
| +
|
| + (*out.mutable_map3())[111] = "one one one";
|
| +
|
| + out.set_bar("top bar");
|
| +
|
| + ow_.StartObject("")
|
| + ->StartObject("map1")
|
| + ->StartObject("key1")
|
| + ->RenderString("foo", "foovalue")
|
| + ->EndObject()
|
| + ->StartObject("key2")
|
| + ->RenderString("foo", "barvalue")
|
| + ->EndObject()
|
| + ->StartObject("map2")
|
| + ->StartObject("nestedself")
|
| + ->StartObject("map1")
|
| + ->StartObject("nested_key1")
|
| + ->RenderString("foo", "nested_foo")
|
| + ->EndObject()
|
| + ->EndObject()
|
| + ->RenderString("bar", "nested_bar_string")
|
| + ->EndObject()
|
| + ->EndObject()
|
| + ->StartObject("map3")
|
| + ->RenderString("111", "one one one")
|
| + ->EndObject()
|
| + ->EndObject()
|
| + ->RenderString("bar", "top bar")
|
| + ->EndObject();
|
| +
|
| + DoTest(out, MapOut::descriptor());
|
| +}
|
| +
|
| +class ProtostreamObjectSourceAnysTest : public ProtostreamObjectSourceTest {
|
| + protected:
|
| + ProtostreamObjectSourceAnysTest() {
|
| + helper_.ResetTypeInfo(AnyOut::descriptor(),
|
| + google::protobuf::Any::descriptor());
|
| + }
|
| +};
|
| +
|
| +INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
|
| + ProtostreamObjectSourceAnysTest,
|
| + ::testing::Values(
|
| + testing::USE_TYPE_RESOLVER));
|
| +
|
| +// Tests JSON any support.
|
| +//
|
| +// This is the example expected output.
|
| +// {
|
| +// "any": {
|
| +// "@type": "type.googleapis.com/google.protobuf.testing.anys.AnyM"
|
| +// "foo": "foovalue"
|
| +// }
|
| +// }
|
| +TEST_P(ProtostreamObjectSourceAnysTest, BasicAny) {
|
| + AnyOut out;
|
| + ::google::protobuf::Any* any = out.mutable_any();
|
| +
|
| + AnyM m;
|
| + m.set_foo("foovalue");
|
| + any->PackFrom(m);
|
| +
|
| + ow_.StartObject("")
|
| + ->StartObject("any")
|
| + ->RenderString("@type",
|
| + "type.googleapis.com/google.protobuf.testing.anys.AnyM")
|
| + ->RenderString("foo", "foovalue")
|
| + ->EndObject()
|
| + ->EndObject();
|
| +
|
| + DoTest(out, AnyOut::descriptor());
|
| +}
|
| +
|
| +TEST_P(ProtostreamObjectSourceAnysTest, RecursiveAny) {
|
| + AnyOut out;
|
| + ::google::protobuf::Any* any = out.mutable_any();
|
| + any->set_type_url("type.googleapis.com/google.protobuf.Any");
|
| +
|
| + ::google::protobuf::Any nested_any;
|
| + nested_any.set_type_url(
|
| + "type.googleapis.com/google.protobuf.testing.anys.AnyM");
|
| +
|
| + AnyM m;
|
| + m.set_foo("foovalue");
|
| + nested_any.set_value(m.SerializeAsString());
|
| +
|
| + any->set_value(nested_any.SerializeAsString());
|
| +
|
| + ow_.StartObject("")
|
| + ->StartObject("any")
|
| + ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
|
| + ->StartObject("value")
|
| + ->RenderString("@type",
|
| + "type.googleapis.com/google.protobuf.testing.anys.AnyM")
|
| + ->RenderString("foo", "foovalue")
|
| + ->EndObject()
|
| + ->EndObject()
|
| + ->EndObject();
|
| +
|
| + DoTest(out, AnyOut::descriptor());
|
| +}
|
| +
|
| +TEST_P(ProtostreamObjectSourceAnysTest, DoubleRecursiveAny) {
|
| + AnyOut out;
|
| + ::google::protobuf::Any* any = out.mutable_any();
|
| + any->set_type_url("type.googleapis.com/google.protobuf.Any");
|
| +
|
| + ::google::protobuf::Any nested_any;
|
| + nested_any.set_type_url("type.googleapis.com/google.protobuf.Any");
|
| +
|
| + ::google::protobuf::Any second_nested_any;
|
| + second_nested_any.set_type_url(
|
| + "type.googleapis.com/google.protobuf.testing.anys.AnyM");
|
| +
|
| + AnyM m;
|
| + m.set_foo("foovalue");
|
| + second_nested_any.set_value(m.SerializeAsString());
|
| + nested_any.set_value(second_nested_any.SerializeAsString());
|
| + any->set_value(nested_any.SerializeAsString());
|
| +
|
| + ow_.StartObject("")
|
| + ->StartObject("any")
|
| + ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
|
| + ->StartObject("value")
|
| + ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
|
| + ->StartObject("value")
|
| + ->RenderString("@type",
|
| + "type.googleapis.com/google.protobuf.testing.anys.AnyM")
|
| + ->RenderString("foo", "foovalue")
|
| + ->EndObject()
|
| + ->EndObject()
|
| + ->EndObject()
|
| + ->EndObject();
|
| +
|
| + DoTest(out, AnyOut::descriptor());
|
| +}
|
| +
|
| +TEST_P(ProtostreamObjectSourceAnysTest, EmptyAnyOutputsEmptyObject) {
|
| + AnyOut out;
|
| + out.mutable_any();
|
| +
|
| + ow_.StartObject("")->StartObject("any")->EndObject()->EndObject();
|
| +
|
| + DoTest(out, AnyOut::descriptor());
|
| +}
|
| +
|
| +TEST_P(ProtostreamObjectSourceAnysTest, EmptyWithTypeAndNoValueOutputsType) {
|
| + AnyOut out;
|
| + out.mutable_any()->set_type_url("foo.googleapis.com/my.Type");
|
| +
|
| + ow_.StartObject("")
|
| + ->StartObject("any")
|
| + ->RenderString("@type", "foo.googleapis.com/my.Type")
|
| + ->EndObject()
|
| + ->EndObject();
|
| +
|
| + DoTest(out, AnyOut::descriptor());
|
| +}
|
| +
|
| +TEST_P(ProtostreamObjectSourceAnysTest, MissingTypeUrlError) {
|
| + AnyOut out;
|
| + ::google::protobuf::Any* any = out.mutable_any();
|
| +
|
| + AnyM m;
|
| + m.set_foo("foovalue");
|
| + any->set_value(m.SerializeAsString());
|
| +
|
| + // We start the "AnyOut" part and then fail when we hit the Any object.
|
| + ow_.StartObject("");
|
| +
|
| + Status status = ExecuteTest(out, AnyOut::descriptor());
|
| + EXPECT_EQ(util::error::INTERNAL, status.error_code());
|
| +}
|
| +
|
| +TEST_P(ProtostreamObjectSourceAnysTest, UnknownTypeServiceError) {
|
| + AnyOut out;
|
| + ::google::protobuf::Any* any = out.mutable_any();
|
| + any->set_type_url("foo.googleapis.com/my.own.Type");
|
| +
|
| + AnyM m;
|
| + m.set_foo("foovalue");
|
| + any->set_value(m.SerializeAsString());
|
| +
|
| + // We start the "AnyOut" part and then fail when we hit the Any object.
|
| + ow_.StartObject("");
|
| +
|
| + Status status = ExecuteTest(out, AnyOut::descriptor());
|
| + EXPECT_EQ(util::error::INTERNAL, status.error_code());
|
| +}
|
| +
|
| +TEST_P(ProtostreamObjectSourceAnysTest, UnknownTypeError) {
|
| + AnyOut out;
|
| + ::google::protobuf::Any* any = out.mutable_any();
|
| + any->set_type_url("type.googleapis.com/unknown.Type");
|
| +
|
| + AnyM m;
|
| + m.set_foo("foovalue");
|
| + any->set_value(m.SerializeAsString());
|
| +
|
| + // We start the "AnyOut" part and then fail when we hit the Any object.
|
| + ow_.StartObject("");
|
| +
|
| + Status status = ExecuteTest(out, AnyOut::descriptor());
|
| + EXPECT_EQ(util::error::INTERNAL, status.error_code());
|
| +}
|
| +
|
| +class ProtostreamObjectSourceStructTest : public ProtostreamObjectSourceTest {
|
| + protected:
|
| + ProtostreamObjectSourceStructTest() {
|
| + helper_.ResetTypeInfo(StructType::descriptor(),
|
| + google::protobuf::Struct::descriptor());
|
| + }
|
| +};
|
| +
|
| +INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
|
| + ProtostreamObjectSourceStructTest,
|
| + ::testing::Values(
|
| + testing::USE_TYPE_RESOLVER));
|
| +
|
| +// Tests struct
|
| +//
|
| +// "object": {
|
| +// "k1": 123,
|
| +// "k2": true
|
| +// }
|
| +TEST_P(ProtostreamObjectSourceStructTest, StructRenderSuccess) {
|
| + StructType out;
|
| + google::protobuf::Struct* s = out.mutable_object();
|
| + s->mutable_fields()->operator[]("k1").set_number_value(123);
|
| + s->mutable_fields()->operator[]("k2").set_bool_value(true);
|
| +
|
| + ow_.StartObject("")
|
| + ->StartObject("object")
|
| + ->RenderDouble("k1", 123)
|
| + ->RenderBool("k2", true)
|
| + ->EndObject()
|
| + ->EndObject();
|
| +
|
| + DoTest(out, StructType::descriptor());
|
| +}
|
| +
|
| +TEST_P(ProtostreamObjectSourceStructTest, MissingValueSkipsField) {
|
| + StructType out;
|
| + google::protobuf::Struct* s = out.mutable_object();
|
| + s->mutable_fields()->operator[]("k1");
|
| +
|
| + ow_.StartObject("")->StartObject("object")->EndObject()->EndObject();
|
| +
|
| + DoTest(out, StructType::descriptor());
|
| +}
|
| +
|
| +class ProtostreamObjectSourceFieldMaskTest
|
| + : public ProtostreamObjectSourceTest {
|
| + protected:
|
| + ProtostreamObjectSourceFieldMaskTest() {
|
| + helper_.ResetTypeInfo(FieldMaskTest::descriptor(),
|
| + google::protobuf::FieldMask::descriptor());
|
| + }
|
| +};
|
| +
|
| +INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
|
| + ProtostreamObjectSourceFieldMaskTest,
|
| + ::testing::Values(
|
| + testing::USE_TYPE_RESOLVER));
|
| +
|
| +TEST_P(ProtostreamObjectSourceFieldMaskTest, FieldMaskRenderSuccess) {
|
| + FieldMaskTest out;
|
| + out.set_id("1");
|
| + out.mutable_single_mask()->add_paths("path1");
|
| + out.mutable_single_mask()->add_paths("snake_case_path2");
|
| + ::google::protobuf::FieldMask* mask = out.add_repeated_mask();
|
| + mask->add_paths("path3");
|
| + mask = out.add_repeated_mask();
|
| + mask->add_paths("snake_case_path4");
|
| + mask->add_paths("path5");
|
| + NestedFieldMask* nested = out.add_nested_mask();
|
| + nested->set_data("data");
|
| + nested->mutable_single_mask()->add_paths("nested.path1");
|
| + nested->mutable_single_mask()->add_paths("nested_field.snake_case_path2");
|
| + mask = nested->add_repeated_mask();
|
| + mask->add_paths("nested_field.path3");
|
| + mask->add_paths("nested.snake_case_path4");
|
| + mask = nested->add_repeated_mask();
|
| + mask->add_paths("nested.path5");
|
| + mask = nested->add_repeated_mask();
|
| + mask->add_paths(
|
| + "snake_case.map_field[\"map_key_should_be_ignored\"].nested_snake_case."
|
| + "map_field[\"map_key_sho\\\"uld_be_ignored\"]");
|
| +
|
| + ow_.StartObject("")
|
| + ->RenderString("id", "1")
|
| + ->RenderString("singleMask", "path1,snakeCasePath2")
|
| + ->StartList("repeatedMask")
|
| + ->RenderString("", "path3")
|
| + ->RenderString("", "snakeCasePath4,path5")
|
| + ->EndList()
|
| + ->StartList("nestedMask")
|
| + ->StartObject("")
|
| + ->RenderString("data", "data")
|
| + ->RenderString("singleMask", "nested.path1,nestedField.snakeCasePath2")
|
| + ->StartList("repeatedMask")
|
| + ->RenderString("", "nestedField.path3,nested.snakeCasePath4")
|
| + ->RenderString("", "nested.path5")
|
| + ->RenderString("",
|
| + "snakeCase.mapField[\"map_key_should_be_ignored\"]."
|
| + "nestedSnakeCase.mapField[\"map_key_sho\\\"uld_be_"
|
| + "ignored\"]")
|
| + ->EndList()
|
| + ->EndObject()
|
| + ->EndList()
|
| + ->EndObject();
|
| +
|
| + DoTest(out, FieldMaskTest::descriptor());
|
| +}
|
| +
|
| +} // namespace converter
|
| +} // namespace util
|
| +} // namespace protobuf
|
| +} // namespace google
|
|
|