Index: third_party/protobuf/src/google/protobuf/util/internal/protostream_objectwriter_test.cc |
diff --git a/third_party/protobuf/src/google/protobuf/util/internal/protostream_objectwriter_test.cc b/third_party/protobuf/src/google/protobuf/util/internal/protostream_objectwriter_test.cc |
index 9a0dcde1c4d1de29f19fb18948adc3d3c1c35fa9..a9b15e68a858443cbcbbc8ca6881cfbc8e73dc0f 100644 |
--- a/third_party/protobuf/src/google/protobuf/util/internal/protostream_objectwriter_test.cc |
+++ b/third_party/protobuf/src/google/protobuf/util/internal/protostream_objectwriter_test.cc |
@@ -41,18 +41,20 @@ |
#include <google/protobuf/dynamic_message.h> |
#include <google/protobuf/message.h> |
#include <google/protobuf/util/internal/mock_error_listener.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/oneofs.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/testdata/wrappers.pb.h> |
#include <google/protobuf/util/internal/type_info_test_helper.h> |
#include <google/protobuf/util/internal/constants.h> |
#include <google/protobuf/util/message_differencer.h> |
#include <google/protobuf/stubs/bytestream.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/oneofs.pb.h> |
-#include <google/protobuf/util/internal/testdata/struct.pb.h> |
-#include <google/protobuf/util/internal/testdata/timestamp_duration.pb.h> |
#include <gtest/gtest.h> |
@@ -61,27 +63,28 @@ namespace protobuf { |
namespace util { |
namespace converter { |
+using google::protobuf::testing::AnyM; |
+using google::protobuf::testing::AnyOut; |
using google::protobuf::testing::Author; |
using google::protobuf::testing::Book; |
-using google::protobuf::testing::Book_Data; |
+using google::protobuf::testing::FieldMaskTest; |
+using google::protobuf::testing::Int32Wrapper; |
+using google::protobuf::testing::MapIn; |
using google::protobuf::testing::Primitive; |
+using google::protobuf::testing::Proto3Message; |
using google::protobuf::testing::Publisher; |
+using google::protobuf::testing::StructType; |
+using google::protobuf::testing::TimestampDuration; |
+using google::protobuf::testing::ValueWrapper; |
+using google::protobuf::testing::oneofs::OneOfsRequest; |
using google::protobuf::Descriptor; |
using google::protobuf::DescriptorPool; |
using google::protobuf::DynamicMessageFactory; |
using google::protobuf::FileDescriptorProto; |
using google::protobuf::Message; |
-using google::protobuf::io::ArrayInputStream; |
using strings::GrowingArrayByteSink; |
using ::testing::_; |
using ::testing::Args; |
-using google::protobuf::testing::anys::AnyM; |
-using google::protobuf::testing::anys::AnyOut; |
-using google::protobuf::testing::oneofs::OneOfsRequest; |
-using google::protobuf::testing::FieldMaskTest; |
-using google::protobuf::testing::maps::MapIn; |
-using google::protobuf::testing::structs::StructType; |
-using google::protobuf::testing::timestampduration::TimestampDuration; |
namespace { |
@@ -110,13 +113,13 @@ class BaseProtoStreamObjectWriterTest |
listener_(), |
output_(new GrowingArrayByteSink(1000)), |
ow_() { |
- vector<const Descriptor*> descriptors; |
+ std::vector<const Descriptor*> descriptors; |
descriptors.push_back(descriptor); |
ResetTypeInfo(descriptors); |
} |
explicit BaseProtoStreamObjectWriterTest( |
- vector<const Descriptor*> descriptors) |
+ std::vector<const Descriptor*> descriptors) |
: helper_(GetParam()), |
listener_(), |
output_(new GrowingArrayByteSink(1000)), |
@@ -124,7 +127,7 @@ class BaseProtoStreamObjectWriterTest |
ResetTypeInfo(descriptors); |
} |
- void ResetTypeInfo(vector<const Descriptor*> descriptors) { |
+ void ResetTypeInfo(std::vector<const Descriptor*> descriptors) { |
GOOGLE_CHECK(!descriptors.empty()) << "Must have at least one descriptor!"; |
helper_.ResetTypeInfo(descriptors); |
ow_.reset(helper_.NewProtoWriter(GetTypeUrl(descriptors[0]), output_.get(), |
@@ -132,7 +135,7 @@ class BaseProtoStreamObjectWriterTest |
} |
void ResetTypeInfo(const Descriptor* descriptor) { |
- vector<const Descriptor*> descriptors; |
+ std::vector<const Descriptor*> descriptors; |
descriptors.push_back(descriptor); |
ResetTypeInfo(descriptors); |
} |
@@ -183,6 +186,10 @@ class ProtoStreamObjectWriterTest : public BaseProtoStreamObjectWriterTest { |
ProtoStreamObjectWriterTest() |
: BaseProtoStreamObjectWriterTest(Book::descriptor()) {} |
+ void ResetProtoWriter() { |
+ ResetTypeInfo(Book::descriptor()); |
+ } |
+ |
virtual ~ProtoStreamObjectWriterTest() {} |
}; |
@@ -264,6 +271,84 @@ TEST_P(ProtoStreamObjectWriterTest, CustomJsonName) { |
CheckOutput(book); |
} |
+TEST_P(ProtoStreamObjectWriterTest, IntEnumValuesAreAccepted) { |
+ Book book; |
+ book.set_title("Some Book"); |
+ book.set_type(google::protobuf::testing::Book_Type_KIDS); |
+ Author* robert = book.mutable_author(); |
+ robert->set_name("robert"); |
+ |
+ ow_->StartObject("") |
+ ->RenderString("title", "Some Book") |
+ ->RenderString("type", "2") |
+ ->StartObject("author") |
+ ->RenderString("name", "robert") |
+ ->EndObject() |
+ ->EndObject(); |
+ CheckOutput(book); |
+} |
+ |
+TEST_P(ProtoStreamObjectWriterTest, EnumValuesWithoutUnderscoreAreAccepted) { |
+ Book book; |
+ book.set_title("Some Book"); |
+ book.set_type(google::protobuf::testing::Book_Type_ACTION_AND_ADVENTURE); |
+ Author* robert = book.mutable_author(); |
+ robert->set_name("robert"); |
+ |
+ options_.use_lower_camel_for_enums = true; |
+ ResetProtoWriter(); |
+ |
+ ow_->StartObject("") |
+ ->RenderString("title", "Some Book") |
+ ->RenderString("type", "ACTIONANDADVENTURE") |
+ ->StartObject("author") |
+ ->RenderString("name", "robert") |
+ ->EndObject() |
+ ->EndObject(); |
+ CheckOutput(book); |
+} |
+ |
+TEST_P(ProtoStreamObjectWriterTest, EnumValuesInCamelCaseAreAccepted) { |
+ Book book; |
+ book.set_title("Some Book"); |
+ book.set_type(google::protobuf::testing::Book_Type_ACTION_AND_ADVENTURE); |
+ Author* robert = book.mutable_author(); |
+ robert->set_name("robert"); |
+ |
+ options_.use_lower_camel_for_enums = true; |
+ ResetProtoWriter(); |
+ |
+ ow_->StartObject("") |
+ ->RenderString("title", "Some Book") |
+ ->RenderString("type", "actionAndAdventure") |
+ ->StartObject("author") |
+ ->RenderString("name", "robert") |
+ ->EndObject() |
+ ->EndObject(); |
+ CheckOutput(book); |
+} |
+ |
+TEST_P(ProtoStreamObjectWriterTest, |
+ EnumValuesInCamelCaseWithNameNotUppercaseAreAccepted) { |
+ Book book; |
+ book.set_title("Some Book"); |
+ book.set_type(google::protobuf::testing::Book_Type_arts_and_photography); |
+ Author* robert = book.mutable_author(); |
+ robert->set_name("robert"); |
+ |
+ options_.use_lower_camel_for_enums = true; |
+ ResetProtoWriter(); |
+ |
+ ow_->StartObject("") |
+ ->RenderString("title", "Some Book") |
+ ->RenderString("type", "artsAndPhotography") |
+ ->StartObject("author") |
+ ->RenderString("name", "robert") |
+ ->EndObject() |
+ ->EndObject(); |
+ CheckOutput(book); |
+} |
+ |
TEST_P(ProtoStreamObjectWriterTest, PrimitiveFromStringConversion) { |
Primitive full; |
full.set_fix32(101); |
@@ -709,6 +794,132 @@ TEST_P(ProtoStreamObjectWriterTest, UnknownListAtPublisher) { |
CheckOutput(expected); |
} |
+TEST_P(ProtoStreamObjectWriterTest, IgnoreUnknownFieldAtRoot) { |
+ Book empty; |
+ |
+ options_.ignore_unknown_fields = true; |
+ ResetProtoWriter(); |
+ |
+ EXPECT_CALL(listener_, InvalidName(_, _, _)).Times(0); |
+ ow_->StartObject("")->RenderString("unknown", "Nope!")->EndObject(); |
+ CheckOutput(empty, 0); |
+} |
+ |
+TEST_P(ProtoStreamObjectWriterTest, IgnoreUnknownFieldAtAuthorFriend) { |
+ Book expected; |
+ Author* paul = expected.mutable_author(); |
+ paul->set_name("Paul"); |
+ Author* mark = paul->add_friend_(); |
+ mark->set_name("Mark"); |
+ Author* john = paul->add_friend_(); |
+ john->set_name("John"); |
+ Author* luke = paul->add_friend_(); |
+ luke->set_name("Luke"); |
+ |
+ options_.ignore_unknown_fields = true; |
+ ResetProtoWriter(); |
+ |
+ EXPECT_CALL(listener_, InvalidName(_, _, _)).Times(0); |
+ ow_->StartObject("") |
+ ->StartObject("author") |
+ ->RenderString("name", "Paul") |
+ ->StartList("friend") |
+ ->StartObject("") |
+ ->RenderString("name", "Mark") |
+ ->EndObject() |
+ ->StartObject("") |
+ ->RenderString("name", "John") |
+ ->RenderString("address", "Patmos") |
+ ->EndObject() |
+ ->StartObject("") |
+ ->RenderString("name", "Luke") |
+ ->EndObject() |
+ ->EndList() |
+ ->EndObject() |
+ ->EndObject(); |
+ CheckOutput(expected); |
+} |
+ |
+TEST_P(ProtoStreamObjectWriterTest, IgnoreUnknownObjectAtRoot) { |
+ Book empty; |
+ |
+ options_.ignore_unknown_fields = true; |
+ ResetProtoWriter(); |
+ |
+ EXPECT_CALL(listener_, InvalidName(_, StringPiece("unknown"), |
+ StringPiece("Cannot find field."))) |
+ .Times(0); |
+ ow_->StartObject("")->StartObject("unknown")->EndObject()->EndObject(); |
+ CheckOutput(empty, 0); |
+} |
+ |
+TEST_P(ProtoStreamObjectWriterTest, IgnoreUnknownObjectAtAuthor) { |
+ Book expected; |
+ Author* author = expected.mutable_author(); |
+ author->set_name("William"); |
+ author->add_pseudonym("Bill"); |
+ |
+ options_.ignore_unknown_fields = true; |
+ ResetProtoWriter(); |
+ |
+ EXPECT_CALL(listener_, InvalidName(_, _, _)).Times(0); |
+ ow_->StartObject("") |
+ ->StartObject("author") |
+ ->RenderString("name", "William") |
+ ->StartObject("wife") |
+ ->RenderString("name", "Hilary") |
+ ->EndObject() |
+ ->RenderString("pseudonym", "Bill") |
+ ->EndObject() |
+ ->EndObject(); |
+ CheckOutput(expected); |
+} |
+ |
+TEST_P(ProtoStreamObjectWriterTest, IgnoreUnknownListAtRoot) { |
+ Book empty; |
+ |
+ options_.ignore_unknown_fields = true; |
+ ResetProtoWriter(); |
+ |
+ EXPECT_CALL(listener_, InvalidName(_, _, _)).Times(0); |
+ ow_->StartObject("")->StartList("unknown")->EndList()->EndObject(); |
+ CheckOutput(empty, 0); |
+} |
+ |
+TEST_P(ProtoStreamObjectWriterTest, IgnoreUnknownListAtPublisher) { |
+ Book expected; |
+ expected.set_title("Brainwashing"); |
+ Publisher* publisher = expected.mutable_publisher(); |
+ publisher->set_name("propaganda"); |
+ |
+ options_.ignore_unknown_fields = true; |
+ ResetProtoWriter(); |
+ |
+ EXPECT_CALL(listener_, InvalidName(_, _, _)).Times(0); |
+ ow_->StartObject("") |
+ ->StartObject("publisher") |
+ ->RenderString("name", "propaganda") |
+ ->StartList("alliance") |
+ ->EndList() |
+ ->EndObject() |
+ ->RenderString("title", "Brainwashing") |
+ ->EndObject(); |
+ CheckOutput(expected); |
+} |
+ |
+TEST_P(ProtoStreamObjectWriterTest, AcceptUnknownEnumValue) { |
+ ResetTypeInfo(Proto3Message::descriptor()); |
+ |
+ Proto3Message expected; |
+ expected.set_enum_value(static_cast<Proto3Message::NestedEnum>(12345)); |
+ |
+ EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0); |
+ ow_->StartObject("") |
+ ->RenderInt32("enumValue", 12345) |
+ ->EndObject(); |
+ CheckOutput(expected); |
+} |
+ |
TEST_P(ProtoStreamObjectWriterTest, MissingRequiredField) { |
Book expected; |
expected.set_title("My Title"); |
@@ -867,7 +1078,7 @@ class ProtoStreamObjectWriterTimestampDurationTest |
: public BaseProtoStreamObjectWriterTest { |
protected: |
ProtoStreamObjectWriterTimestampDurationTest() { |
- vector<const Descriptor*> descriptors; |
+ std::vector<const Descriptor*> descriptors; |
descriptors.push_back(TimestampDuration::descriptor()); |
descriptors.push_back(google::protobuf::Timestamp::descriptor()); |
descriptors.push_back(google::protobuf::Duration::descriptor()); |
@@ -1221,9 +1432,9 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, |
InvalidValue( |
_, StringPiece("type.googleapis.com/google.protobuf.Timestamp"), |
StringPiece( |
- "Field 'ts', Invalid data type for timestamp, value is null"))) |
+ "Field 'ts', Invalid data type for timestamp, value is 1"))) |
.With(Args<0>(HasObjectLocation("ts"))); |
- ow_->StartObject("")->RenderNull("ts")->EndObject(); |
+ ow_->StartObject("")->RenderInt32("ts", 1)->EndObject(); |
CheckOutput(timestamp); |
} |
@@ -1235,8 +1446,22 @@ TEST_P(ProtoStreamObjectWriterTimestampDurationTest, |
InvalidValue( |
_, StringPiece("type.googleapis.com/google.protobuf.Duration"), |
StringPiece( |
- "Field 'dur', Invalid data type for duration, value is null"))) |
+ "Field 'dur', Invalid data type for duration, value is 1"))) |
.With(Args<0>(HasObjectLocation("dur"))); |
+ ow_->StartObject("")->RenderInt32("dur", 1)->EndObject(); |
+ CheckOutput(duration); |
+} |
+ |
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest, TimestampAcceptsNull) { |
+ TimestampDuration timestamp; |
+ EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0); |
+ ow_->StartObject("")->RenderNull("ts")->EndObject(); |
+ CheckOutput(timestamp); |
+} |
+ |
+TEST_P(ProtoStreamObjectWriterTimestampDurationTest, DurationAcceptsNull) { |
+ TimestampDuration duration; |
+ EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0); |
ow_->StartObject("")->RenderNull("dur")->EndObject(); |
CheckOutput(duration); |
} |
@@ -1248,7 +1473,7 @@ class ProtoStreamObjectWriterStructTest |
// Resets ProtoWriter with current set of options and other state. |
void ResetProtoWriter() { |
- vector<const Descriptor*> descriptors; |
+ std::vector<const Descriptor*> descriptors; |
descriptors.push_back(StructType::descriptor()); |
descriptors.push_back(google::protobuf::Struct::descriptor()); |
ResetTypeInfo(descriptors); |
@@ -1298,6 +1523,28 @@ TEST_P(ProtoStreamObjectWriterStructTest, StructInvalidInputFailure) { |
CheckOutput(struct_type); |
} |
+TEST_P(ProtoStreamObjectWriterStructTest, StructAcceptsNull) { |
+ StructType struct_type; |
+ EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0); |
+ |
+ ow_->StartObject("")->RenderNull("object")->EndObject(); |
+ CheckOutput(struct_type); |
+} |
+ |
+TEST_P(ProtoStreamObjectWriterStructTest, StructValuePreservesNull) { |
+ StructType struct_type; |
+ (*struct_type.mutable_object()->mutable_fields())["key"].set_null_value( |
+ google::protobuf::NULL_VALUE); |
+ EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0); |
+ |
+ ow_->StartObject("") |
+ ->StartObject("object") |
+ ->RenderNull("key") |
+ ->EndObject() |
+ ->EndObject(); |
+ CheckOutput(struct_type); |
+} |
+ |
TEST_P(ProtoStreamObjectWriterStructTest, SimpleRepeatedStructMapKeyTest) { |
EXPECT_CALL( |
listener_, |
@@ -1365,6 +1612,15 @@ TEST_P(ProtoStreamObjectWriterStructTest, OptionStructIntAsStringsTest) { |
CheckOutput(struct_type); |
} |
+TEST_P(ProtoStreamObjectWriterStructTest, ValuePreservesNull) { |
+ ValueWrapper value; |
+ value.mutable_value()->set_null_value(google::protobuf::NULL_VALUE); |
+ |
+ EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0); |
+ ow_->StartObject("")->RenderNull("value")->EndObject(); |
+ CheckOutput(value); |
+} |
+ |
class ProtoStreamObjectWriterMapTest : public BaseProtoStreamObjectWriterTest { |
protected: |
ProtoStreamObjectWriterMapTest() |
@@ -1408,13 +1664,16 @@ TEST_P(ProtoStreamObjectWriterMapTest, RepeatedMapKeyTest) { |
class ProtoStreamObjectWriterAnyTest : public BaseProtoStreamObjectWriterTest { |
protected: |
ProtoStreamObjectWriterAnyTest() { |
- vector<const Descriptor*> descriptors; |
+ std::vector<const Descriptor*> descriptors; |
descriptors.push_back(AnyOut::descriptor()); |
+ descriptors.push_back(Book::descriptor()); |
+ descriptors.push_back(google::protobuf::Any::descriptor()); |
descriptors.push_back(google::protobuf::DoubleValue::descriptor()); |
+ descriptors.push_back(google::protobuf::FieldMask::descriptor()); |
+ descriptors.push_back(google::protobuf::Int32Value::descriptor()); |
+ descriptors.push_back(google::protobuf::Struct::descriptor()); |
descriptors.push_back(google::protobuf::Timestamp::descriptor()); |
- descriptors.push_back(google::protobuf::Any::descriptor()); |
descriptors.push_back(google::protobuf::Value::descriptor()); |
- descriptors.push_back(google::protobuf::Struct::descriptor()); |
ResetTypeInfo(descriptors); |
} |
}; |
@@ -1447,8 +1706,7 @@ TEST_P(ProtoStreamObjectWriterAnyTest, RecursiveAny) { |
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"); |
+ nested_any.set_type_url("type.googleapis.com/google.protobuf.testing.AnyM"); |
AnyM m; |
m.set_foo("foovalue"); |
@@ -1461,11 +1719,12 @@ TEST_P(ProtoStreamObjectWriterAnyTest, RecursiveAny) { |
->RenderString("@type", "type.googleapis.com/google.protobuf.Any") |
->StartObject("value") |
->RenderString("@type", |
- "type.googleapis.com/google.protobuf.testing.anys.AnyM") |
+ "type.googleapis.com/google.protobuf.testing.AnyM") |
->RenderString("foo", "foovalue") |
->EndObject() |
->EndObject() |
->EndObject(); |
+ CheckOutput(out, 107); |
} |
TEST_P(ProtoStreamObjectWriterAnyTest, DoubleRecursiveAny) { |
@@ -1478,7 +1737,7 @@ TEST_P(ProtoStreamObjectWriterAnyTest, DoubleRecursiveAny) { |
::google::protobuf::Any second_nested_any; |
second_nested_any.set_type_url( |
- "type.googleapis.com/google.protobuf.testing.anys.AnyM"); |
+ "type.googleapis.com/google.protobuf.testing.AnyM"); |
AnyM m; |
m.set_foo("foovalue"); |
@@ -1494,18 +1753,110 @@ TEST_P(ProtoStreamObjectWriterAnyTest, DoubleRecursiveAny) { |
->RenderString("@type", "type.googleapis.com/google.protobuf.Any") |
->StartObject("value") |
->RenderString("@type", |
- "type.googleapis.com/google.protobuf.testing.anys.AnyM") |
+ "type.googleapis.com/google.protobuf.testing.AnyM") |
->RenderString("foo", "foovalue") |
->EndObject() |
->EndObject() |
->EndObject() |
->EndObject(); |
+ CheckOutput(out, 151); |
+} |
+ |
+TEST_P(ProtoStreamObjectWriterAnyTest, TypeUrlAtEnd) { |
+ Book book; |
+ book.set_title("C++"); |
+ book.set_length(1234); |
+ book.set_content("Hello World!"); |
+ |
+ ::google::protobuf::Any any; |
+ any.PackFrom(book); |
+ |
+ ::google::protobuf::Any outer_any; |
+ outer_any.PackFrom(any); |
+ |
+ AnyOut out; |
+ out.mutable_any()->PackFrom(outer_any); |
+ |
+ // Put the @type field at the end of each Any message. Parsers should |
+ // be able to accept that. |
+ ow_->StartObject("") |
+ ->StartObject("any") |
+ ->StartObject("value") |
+ ->StartObject("value") |
+ ->RenderString("title", "C++") |
+ ->RenderInt32("length", 1234) |
+ ->RenderBytes("content", "Hello World!") |
+ ->RenderString("@type", |
+ "type.googleapis.com/google.protobuf.testing.Book") |
+ ->EndObject() |
+ ->RenderString("@type", "type.googleapis.com/google.protobuf.Any") |
+ ->EndObject() |
+ ->RenderString("@type", "type.googleapis.com/google.protobuf.Any") |
+ ->EndObject() |
+ ->EndObject(); |
+ CheckOutput(out); |
+} |
+ |
+// Same as TypeUrlAtEnd, but use temporary string values to make sure we don't |
+// mistakenly store StringPiece objects pointing to invalid memory. |
+TEST_P(ProtoStreamObjectWriterAnyTest, TypeUrlAtEndWithTemporaryStrings) { |
+ Book book; |
+ book.set_title("C++"); |
+ book.set_length(1234); |
+ book.set_content("Hello World!"); |
+ |
+ ::google::protobuf::Any any; |
+ any.PackFrom(book); |
+ |
+ ::google::protobuf::Any outer_any; |
+ outer_any.PackFrom(any); |
+ |
+ AnyOut out; |
+ out.mutable_any()->PackFrom(outer_any); |
+ |
+ string name, value; |
+ // Put the @type field at the end of each Any message. Parsers should |
+ // be able to accept that. |
+ ow_->StartObject("")->StartObject("any"); |
+ { |
+ ow_->StartObject("value"); |
+ { |
+ ow_->StartObject("value"); |
+ { |
+ name = "title"; |
+ value = "C++"; |
+ ow_->RenderString(name, value); |
+ name = "length"; |
+ ow_->RenderInt32(name, 1234); |
+ name = "content"; |
+ value = "Hello World!"; |
+ ow_->RenderBytes(name, value); |
+ name = "@type"; |
+ value = "type.googleapis.com/google.protobuf.testing.Book"; |
+ ow_->RenderString(name, value); |
+ } |
+ ow_->EndObject(); |
+ |
+ name = "@type"; |
+ value = "type.googleapis.com/google.protobuf.Any"; |
+ ow_->RenderString(name, value); |
+ } |
+ ow_->EndObject(); |
+ |
+ name = "@type"; |
+ value = "type.googleapis.com/google.protobuf.Any"; |
+ ow_->RenderString(name, value); |
+ } |
+ ow_->EndObject()->EndObject(); |
+ CheckOutput(out); |
} |
TEST_P(ProtoStreamObjectWriterAnyTest, EmptyAnyFromEmptyObject) { |
AnyOut out; |
out.mutable_any(); |
+ EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0); |
+ |
ow_->StartObject("")->StartObject("any")->EndObject()->EndObject(); |
CheckOutput(out, 2); |
@@ -1514,11 +1865,10 @@ TEST_P(ProtoStreamObjectWriterAnyTest, EmptyAnyFromEmptyObject) { |
TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails1) { |
AnyOut any; |
- EXPECT_CALL( |
- listener_, |
- InvalidValue(_, StringPiece("Any"), |
- StringPiece("Missing or invalid @type for any field in " |
- "google.protobuf.testing.anys.AnyOut"))); |
+ EXPECT_CALL(listener_, |
+ InvalidValue(_, StringPiece("Any"), |
+ StringPiece("Missing @type for any field in " |
+ "google.protobuf.testing.AnyOut"))); |
ow_->StartObject("") |
->StartObject("any") |
@@ -1532,11 +1882,10 @@ TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails1) { |
TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails2) { |
AnyOut any; |
- EXPECT_CALL( |
- listener_, |
- InvalidValue(_, StringPiece("Any"), |
- StringPiece("Missing or invalid @type for any field in " |
- "google.protobuf.testing.anys.AnyOut"))); |
+ EXPECT_CALL(listener_, |
+ InvalidValue(_, StringPiece("Any"), |
+ StringPiece("Missing @type for any field in " |
+ "google.protobuf.testing.AnyOut"))); |
ow_->StartObject("") |
->StartObject("any") |
@@ -1550,11 +1899,10 @@ TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails2) { |
TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails3) { |
AnyOut any; |
- EXPECT_CALL( |
- listener_, |
- InvalidValue(_, StringPiece("Any"), |
- StringPiece("Missing or invalid @type for any field in " |
- "google.protobuf.testing.anys.AnyOut"))); |
+ EXPECT_CALL(listener_, |
+ InvalidValue(_, StringPiece("Any"), |
+ StringPiece("Missing @type for any field in " |
+ "google.protobuf.testing.AnyOut"))); |
ow_->StartObject("") |
->StartObject("any") |
@@ -1599,9 +1947,21 @@ TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithUnknownTypeFails) { |
CheckOutput(any); |
} |
-TEST_P(ProtoStreamObjectWriterAnyTest, AnyNullInputFails) { |
+TEST_P(ProtoStreamObjectWriterAnyTest, AnyIncorrectInputTypeFails) { |
+ AnyOut any; |
+ |
+ EXPECT_CALL( |
+ listener_, |
+ InvalidValue(_, StringPiece("type.googleapis.com/google.protobuf.Any"), |
+ StringPiece("1"))); |
+ ow_->StartObject("")->RenderInt32("any", 1)->EndObject(); |
+ CheckOutput(any); |
+} |
+ |
+TEST_P(ProtoStreamObjectWriterAnyTest, AnyAcceptsNull) { |
AnyOut any; |
+ EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0); |
ow_->StartObject("")->RenderNull("any")->EndObject(); |
CheckOutput(any); |
} |
@@ -1839,11 +2199,116 @@ TEST_P(ProtoStreamObjectWriterAnyTest, AnyWellKnownTypesExpectObjectForAny) { |
CheckOutput(any); |
} |
+// { |
+// "any": { |
+// "@type": "type.googleapis.com/google.protobuf.Any", |
+// "value": null |
+// } |
+// } |
+TEST_P(ProtoStreamObjectWriterAnyTest, AnyInAnyAcceptsNull) { |
+ AnyOut out; |
+ google::protobuf::Any empty; |
+ out.mutable_any()->PackFrom(empty); |
+ |
+ EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0); |
+ ow_->StartObject("") |
+ ->StartObject("any") |
+ ->RenderString("@type", "type.googleapis.com/google.protobuf.Any") |
+ ->RenderNull("value") |
+ ->EndObject() |
+ ->EndObject(); |
+ CheckOutput(out); |
+} |
+ |
+// { |
+// "any": { |
+// "@type": "type.googleapis.com/google.protobuf.Timestamp", |
+// "value": null |
+// } |
+// } |
+TEST_P(ProtoStreamObjectWriterAnyTest, TimestampInAnyAcceptsNull) { |
+ AnyOut out; |
+ google::protobuf::Timestamp empty; |
+ out.mutable_any()->PackFrom(empty); |
+ |
+ EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0); |
+ ow_->StartObject("") |
+ ->StartObject("any") |
+ ->RenderString("@type", "type.googleapis.com/google.protobuf.Timestamp") |
+ ->RenderNull("value") |
+ ->EndObject() |
+ ->EndObject(); |
+ CheckOutput(out); |
+} |
+ |
+// { |
+// "any": { |
+// "@type": "type.googleapis.com/google.protobuf.Duration", |
+// "value": null |
+// } |
+// } |
+TEST_P(ProtoStreamObjectWriterAnyTest, DurationInAnyAcceptsNull) { |
+ AnyOut out; |
+ google::protobuf::Duration empty; |
+ out.mutable_any()->PackFrom(empty); |
+ |
+ EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0); |
+ ow_->StartObject("") |
+ ->StartObject("any") |
+ ->RenderString("@type", "type.googleapis.com/google.protobuf.Duration") |
+ ->RenderNull("value") |
+ ->EndObject() |
+ ->EndObject(); |
+ CheckOutput(out); |
+} |
+ |
+// { |
+// "any": { |
+// "@type": "type.googleapis.com/google.protobuf.FieldMask", |
+// "value": null |
+// } |
+// } |
+TEST_P(ProtoStreamObjectWriterAnyTest, FieldMaskInAnyAcceptsNull) { |
+ AnyOut out; |
+ google::protobuf::FieldMask empty; |
+ out.mutable_any()->PackFrom(empty); |
+ |
+ EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0); |
+ ow_->StartObject("") |
+ ->StartObject("any") |
+ ->RenderString("@type", "type.googleapis.com/google.protobuf.FieldMask") |
+ ->RenderNull("value") |
+ ->EndObject() |
+ ->EndObject(); |
+ CheckOutput(out); |
+} |
+ |
+// { |
+// "any": { |
+// "@type": "type.googleapis.com/google.protobuf.Int32Value", |
+// "value": null |
+// } |
+// } |
+TEST_P(ProtoStreamObjectWriterAnyTest, WrapperInAnyAcceptsNull) { |
+ AnyOut out; |
+ google::protobuf::Int32Value empty; |
+ out.mutable_any()->PackFrom(empty); |
+ |
+ EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0); |
+ ow_->StartObject("") |
+ ->StartObject("any") |
+ ->RenderString("@type", "type.googleapis.com/google.protobuf.Int32Value") |
+ ->RenderNull("value") |
+ ->EndObject() |
+ ->EndObject(); |
+ CheckOutput(out); |
+} |
+ |
class ProtoStreamObjectWriterFieldMaskTest |
: public BaseProtoStreamObjectWriterTest { |
protected: |
ProtoStreamObjectWriterFieldMaskTest() { |
- vector<const Descriptor*> descriptors; |
+ std::vector<const Descriptor*> descriptors; |
descriptors.push_back(FieldMaskTest::descriptor()); |
descriptors.push_back(google::protobuf::FieldMask::descriptor()); |
ResetTypeInfo(descriptors); |
@@ -2084,11 +2549,41 @@ TEST_P(ProtoStreamObjectWriterFieldMaskTest, MapKeyCanContainAnyChars) { |
CheckOutput(expected); |
} |
+TEST_P(ProtoStreamObjectWriterFieldMaskTest, FieldMaskAcceptsNull) { |
+ FieldMaskTest expected; |
+ EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0); |
+ ow_->StartObject("")->RenderNull("single_mask")->EndObject(); |
+ CheckOutput(expected); |
+} |
+ |
+class ProtoStreamObjectWriterWrappersTest |
+ : public BaseProtoStreamObjectWriterTest { |
+ protected: |
+ ProtoStreamObjectWriterWrappersTest() { |
+ std::vector<const Descriptor*> descriptors; |
+ descriptors.push_back(Int32Wrapper::descriptor()); |
+ descriptors.push_back(google::protobuf::Int32Value::descriptor()); |
+ ResetTypeInfo(descriptors); |
+ } |
+}; |
+ |
+INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest, |
+ ProtoStreamObjectWriterWrappersTest, |
+ ::testing::Values( |
+ testing::USE_TYPE_RESOLVER)); |
+ |
+TEST_P(ProtoStreamObjectWriterWrappersTest, WrapperAcceptsNull) { |
+ Int32Wrapper wrapper; |
+ EXPECT_CALL(listener_, InvalidName(_, _, _)).Times(0); |
+ ow_->StartObject("")->RenderNull("int32")->EndObject(); |
+ CheckOutput(wrapper); |
+} |
+ |
class ProtoStreamObjectWriterOneOfsTest |
: public BaseProtoStreamObjectWriterTest { |
protected: |
ProtoStreamObjectWriterOneOfsTest() { |
- vector<const Descriptor*> descriptors; |
+ std::vector<const Descriptor*> descriptors; |
descriptors.push_back(OneOfsRequest::descriptor()); |
descriptors.push_back(google::protobuf::Struct::descriptor()); |
ResetTypeInfo(descriptors); |
@@ -2251,7 +2746,6 @@ TEST_P(ProtoStreamObjectWriterOneOfsTest, |
StringPiece("oneof field 'data' is already set. " |
"Cannot set 'intData'"))); |
- using google::protobuf::testing::oneofs::OneOfsRequest; |
// JSON: |
// { "anyData": |
// { "@type": |