| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088 |
- // 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>
- #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/anys.pb.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/testdata/maps.pb.h>
- #include <google/protobuf/util/internal/testdata/proto3.pb.h>
- #include <google/protobuf/util/internal/testdata/struct.pb.h>
- #include <google/protobuf/util/internal/testdata/timestamp_duration.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 <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::AnyM;
- using google::protobuf::testing::AnyOut;
- 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::Cyclic;
- using google::protobuf::testing::FieldMaskTest;
- using google::protobuf::testing::MapOut;
- using google::protobuf::testing::MapOutWireFormat;
- using google::protobuf::testing::NestedBook;
- using google::protobuf::testing::NestedFieldMask;
- using google::protobuf::testing::PackedPrimitive;
- using google::protobuf::testing::Primitive;
- using google::protobuf::testing::Proto3Message;
- using google::protobuf::testing::StructType;
- using google::protobuf::testing::TimestampDuration;
- 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_),
- use_lower_camel_for_enums_(false),
- use_ints_for_enums_(false),
- add_trailing_zeros_(false),
- render_unknown_enum_values_(true) {
- helper_.ResetTypeInfo(Book::descriptor(), Proto3Message::descriptor());
- }
- virtual ~ProtostreamObjectSourceTest() {}
- void DoTest(const Message& msg, const Descriptor* descriptor) {
- Status status = ExecuteTest(msg, descriptor);
- EXPECT_EQ(util::Status(), status);
- }
- Status ExecuteTest(const Message& msg, const Descriptor* descriptor) {
- std::ostringstream oss;
- msg.SerializePartialToOstream(&oss);
- string proto = oss.str();
- ArrayInputStream arr_stream(proto.data(), proto.size());
- CodedInputStream in_stream(&arr_stream);
- std::unique_ptr<ProtoStreamObjectSource> os(
- helper_.NewProtoSource(&in_stream, GetTypeUrl(descriptor)));
- if (use_lower_camel_for_enums_) os->set_use_lower_camel_for_enums(true);
- if (use_ints_for_enums_) os->set_use_ints_for_enums(true);
- os->set_max_recursion_depth(64);
- 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;
- }
- void UseLowerCamelForEnums() { use_lower_camel_for_enums_ = true; }
- void UseIntsForEnums() { use_ints_for_enums_ = true; }
- void AddTrailingZeros() { add_trailing_zeros_ = true; }
- void SetRenderUnknownEnumValues(bool value) {
- render_unknown_enum_values_ = value;
- }
- testing::TypeInfoTestHelper helper_;
- ::testing::NiceMock<MockObjectWriter> mock_;
- ExpectingObjectWriter ow_;
- bool use_lower_camel_for_enums_;
- bool use_ints_for_enums_;
- bool add_trailing_zeros_;
- bool render_unknown_enum_values_;
- };
- 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());
- }
- TEST_P(ProtostreamObjectSourceTest, LowerCamelEnumOutputMacroCase) {
- Book book;
- book.set_type(Book::ACTION_AND_ADVENTURE);
- UseLowerCamelForEnums();
- ow_.StartObject("")->RenderString("type", "actionAndAdventure")->EndObject();
- DoTest(book, Book::descriptor());
- }
- TEST_P(ProtostreamObjectSourceTest, LowerCamelEnumOutputSnakeCase) {
- Book book;
- book.set_type(Book::arts_and_photography);
- UseLowerCamelForEnums();
- ow_.StartObject("")->RenderString("type", "artsAndPhotography")->EndObject();
- DoTest(book, Book::descriptor());
- }
- TEST_P(ProtostreamObjectSourceTest, LowerCamelEnumOutputWithNumber) {
- Book book;
- book.set_type(Book::I18N_Tech);
- UseLowerCamelForEnums();
- ow_.StartObject("")->RenderString("type", "i18nTech")->EndObject();
- DoTest(book, Book::descriptor());
- }
- TEST_P(ProtostreamObjectSourceTest, EnumCaseIsUnchangedByDefault) {
- Book book;
- book.set_type(Book::ACTION_AND_ADVENTURE);
- ow_.StartObject("")
- ->RenderString("type", "ACTION_AND_ADVENTURE")
- ->EndObject();
- DoTest(book, Book::descriptor());
- }
- TEST_P(ProtostreamObjectSourceTest, UseIntsForEnumsTest) {
- Book book;
- book.set_type(Book::ACTION_AND_ADVENTURE);
- UseIntsForEnums();
- ow_.StartObject("")->RenderInt32("type", 3)->EndObject();
- DoTest(book, Book::descriptor());
- }
- TEST_P(ProtostreamObjectSourceTest,
- UnknownEnumAreDroppedWhenRenderUnknownEnumValuesIsUnset) {
- Proto3Message message;
- message.set_enum_value(static_cast<Proto3Message::NestedEnum>(1234));
- SetRenderUnknownEnumValues(false);
- // Unknown enum values are not output.
- ow_.StartObject("")->EndObject();
- DoTest(message, Proto3Message::descriptor());
- }
- TEST_P(ProtostreamObjectSourceTest,
- UnknownEnumAreOutputWhenRenderUnknownEnumValuesIsSet) {
- Proto3Message message;
- message.set_enum_value(static_cast<Proto3Message::NestedEnum>(1234));
- SetRenderUnknownEnumValues(true);
- // Unknown enum values are output.
- ow_.StartObject("")->RenderInt32("enumValue", 1234)->EndObject();
- DoTest(message, Proto3Message::descriptor());
- }
- TEST_P(ProtostreamObjectSourceTest, CyclicMessageDepthTest) {
- Cyclic cyclic;
- cyclic.set_m_int(123);
- Book* book = cyclic.mutable_m_book();
- book->set_title("book title");
- Cyclic* current = cyclic.mutable_m_cyclic();
- Author* current_author = cyclic.add_m_author();
- for (int i = 0; i < 63; ++i) {
- Author* next = current_author->add_friend_();
- next->set_id(i);
- next->set_name(StrCat("author_name_", i));
- next->set_alive(true);
- current_author = next;
- }
- // Recursive message with depth (65) > max (max is 64).
- for (int i = 0; i < 64; ++i) {
- Cyclic* next = current->mutable_m_cyclic();
- next->set_m_str(StrCat("count_", i));
- current = next;
- }
- Status status = ExecuteTest(cyclic, Cyclic::descriptor());
- EXPECT_EQ(util::error::INVALID_ARGUMENT, status.error_code());
- }
- 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());
- }
- TEST_P(ProtostreamObjectSourceMapsTest, MissingKeysTest) {
- // MapOutWireFormat has the same wire representation with MapOut but uses
- // repeated message fields to represent map fields so we can intentionally
- // leave out the key field or the value field of a map entry.
- MapOutWireFormat out;
- // Create some map entries without keys. They will be rendered with the
- // default values ("" for strings, "0" for integers, etc.).
- // {
- // "map1": {
- // "": {
- // "foo": "foovalue"
- // }
- // },
- // "map2": {
- // "": {
- // "map1": {
- // "nested_key1": {
- // "foo": "nested_foo"
- // }
- // }
- // }
- // },
- // "map3": {
- // "0": "one one one"
- // },
- // "map4": {
- // "false": "bool"
- // }
- // }
- out.add_map1()->mutable_value()->set_foo("foovalue");
- MapOut* nested = out.add_map2()->mutable_value();
- (*nested->mutable_map1())["nested_key1"].set_foo("nested_foo");
- out.add_map3()->set_value("one one one");
- out.add_map4()->set_value("bool");
- ow_.StartObject("")
- ->StartObject("map1")
- ->StartObject("")
- ->RenderString("foo", "foovalue")
- ->EndObject()
- ->EndObject()
- ->StartObject("map2")
- ->StartObject("")
- ->StartObject("map1")
- ->StartObject("nested_key1")
- ->RenderString("foo", "nested_foo")
- ->EndObject()
- ->EndObject()
- ->EndObject()
- ->EndObject()
- ->StartObject("map3")
- ->RenderString("0", "one one one")
- ->EndObject()
- ->StartObject("map4")
- ->RenderString("false", "bool")
- ->EndObject()
- ->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.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.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.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.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.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.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());
- }
- class ProtostreamObjectSourceTimestampTest
- : public ProtostreamObjectSourceTest {
- protected:
- ProtostreamObjectSourceTimestampTest() {
- helper_.ResetTypeInfo(TimestampDuration::descriptor());
- }
- };
- INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest,
- ProtostreamObjectSourceTimestampTest,
- ::testing::Values(
- testing::USE_TYPE_RESOLVER));
- TEST_P(ProtostreamObjectSourceTimestampTest, InvalidTimestampBelowMinTest) {
- TimestampDuration out;
- google::protobuf::Timestamp* ts = out.mutable_ts();
- // Min allowed seconds - 1
- ts->set_seconds(kTimestampMinSeconds - 1);
- ow_.StartObject("");
- Status status = ExecuteTest(out, TimestampDuration::descriptor());
- EXPECT_EQ(util::error::INTERNAL, status.error_code());
- }
- TEST_P(ProtostreamObjectSourceTimestampTest, InvalidTimestampAboveMaxTest) {
- TimestampDuration out;
- google::protobuf::Timestamp* ts = out.mutable_ts();
- // Max allowed seconds + 1
- ts->set_seconds(kTimestampMaxSeconds + 1);
- ow_.StartObject("");
- Status status = ExecuteTest(out, TimestampDuration::descriptor());
- EXPECT_EQ(util::error::INTERNAL, status.error_code());
- }
- TEST_P(ProtostreamObjectSourceTimestampTest, InvalidDurationBelowMinTest) {
- TimestampDuration out;
- google::protobuf::Duration* dur = out.mutable_dur();
- // Min allowed seconds - 1
- dur->set_seconds(kDurationMinSeconds - 1);
- ow_.StartObject("");
- Status status = ExecuteTest(out, TimestampDuration::descriptor());
- EXPECT_EQ(util::error::INTERNAL, status.error_code());
- }
- TEST_P(ProtostreamObjectSourceTimestampTest, InvalidDurationAboveMaxTest) {
- TimestampDuration out;
- google::protobuf::Duration* dur = out.mutable_dur();
- // Min allowed seconds + 1
- dur->set_seconds(kDurationMaxSeconds + 1);
- ow_.StartObject("");
- Status status = ExecuteTest(out, TimestampDuration::descriptor());
- EXPECT_EQ(util::error::INTERNAL, status.error_code());
- }
- TEST_P(ProtostreamObjectSourceTimestampTest, TimestampDurationDefaultValue) {
- TimestampDuration out;
- out.mutable_ts()->set_seconds(0);
- out.mutable_dur()->set_seconds(0);
- ow_.StartObject("")
- ->RenderString("ts", "1970-01-01T00:00:00Z")
- ->RenderString("dur", "0s")
- ->EndObject();
- DoTest(out, TimestampDuration::descriptor());
- }
- } // namespace converter
- } // namespace util
- } // namespace protobuf
- } // namespace google
|