Down-integrate internal changes to github. (#5527)
This commit is contained in:
parent
63d107b22f
commit
b5f9a35b16
@ -2848,44 +2848,50 @@ void Generator::GenerateClassField(const GeneratorOptions& options,
|
||||
// fields with presence.
|
||||
if (field->is_map()) {
|
||||
printer->Print(
|
||||
"/** Clears values from the map. The map will be non-null. */\n"
|
||||
"$class$.prototype.$clearername$ = function() {\n"
|
||||
" this.$gettername$().clear();$returnvalue$\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"\n",
|
||||
"class", GetMessagePath(options, field->containing_type()),
|
||||
"clearername", "clear" + JSGetterName(options, field),
|
||||
"gettername", "get" + JSGetterName(options, field),
|
||||
"returnvalue", JSReturnClause(field));
|
||||
"clearername", "clear" + JSGetterName(options, field), "gettername",
|
||||
"get" + JSGetterName(options, field), "returnvalue",
|
||||
JSReturnClause(field));
|
||||
printer->Annotate("clearername", field);
|
||||
} else if (field->is_repeated() ||
|
||||
(field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
|
||||
!field->is_required())) {
|
||||
// Fields where we can delegate to the regular setter.
|
||||
printer->Print(
|
||||
"/** $jsdoc$ */\n"
|
||||
"$class$.prototype.$clearername$ = function() {\n"
|
||||
" this.$settername$($clearedvalue$);$returnvalue$\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"\n",
|
||||
"jsdoc",
|
||||
field->is_repeated() ? "Clears the list making it empty but non-null."
|
||||
: "Clears the message field making it undefined.",
|
||||
"class", GetMessagePath(options, field->containing_type()),
|
||||
"clearername", "clear" + JSGetterName(options, field),
|
||||
"settername", "set" + JSGetterName(options, field),
|
||||
"clearedvalue", (field->is_repeated() ? "[]" : "undefined"),
|
||||
"returnvalue", JSReturnClause(field));
|
||||
"clearername", "clear" + JSGetterName(options, field), "settername",
|
||||
"set" + JSGetterName(options, field), "clearedvalue",
|
||||
(field->is_repeated() ? "[]" : "undefined"), "returnvalue",
|
||||
JSReturnClause(field));
|
||||
printer->Annotate("clearername", field);
|
||||
} else if (HasFieldPresence(options, field)) {
|
||||
// Fields where we can't delegate to the regular setter because it doesn't
|
||||
// accept "undefined" as an argument.
|
||||
printer->Print(
|
||||
"/** Clears the field making it undefined. */\n"
|
||||
"$class$.prototype.$clearername$ = function() {\n"
|
||||
" jspb.Message.set$maybeoneof$Field(this, "
|
||||
"$index$$maybeoneofgroup$, ",
|
||||
"class", GetMessagePath(options, field->containing_type()),
|
||||
"clearername", "clear" + JSGetterName(options, field),
|
||||
"maybeoneof", (field->containing_oneof() ? "Oneof" : ""),
|
||||
"maybeoneofgroup", (field->containing_oneof() ?
|
||||
(", " + JSOneofArray(options, field)) : ""),
|
||||
"clearername", "clear" + JSGetterName(options, field), "maybeoneof",
|
||||
(field->containing_oneof() ? "Oneof" : ""), "maybeoneofgroup",
|
||||
(field->containing_oneof() ? (", " + JSOneofArray(options, field))
|
||||
: ""),
|
||||
"index", JSFieldIndex(field));
|
||||
printer->Annotate("clearername", field);
|
||||
printer->Print(
|
||||
@ -2963,14 +2969,15 @@ void Generator::GenerateRepeatedMessageHelperMethods(
|
||||
" * @param {number=} opt_index\n"
|
||||
" * @return {!$optionaltype$}\n"
|
||||
" */\n"
|
||||
"$class$.prototype.add$name$ = function(opt_value, opt_index) {\n"
|
||||
"$class$.prototype.$addername$ = function(opt_value, opt_index) {\n"
|
||||
" return jspb.Message.addTo$repeatedtag$WrapperField(",
|
||||
"optionaltype", JSTypeName(options, field, BYTES_DEFAULT),
|
||||
"class", GetMessagePath(options, field->containing_type()),
|
||||
"name", JSGetterName(options, field, BYTES_DEFAULT,
|
||||
/* drop_list = */ true),
|
||||
"optionaltype", JSTypeName(options, field, BYTES_DEFAULT), "class",
|
||||
GetMessagePath(options, field->containing_type()), "addername",
|
||||
"add" + JSGetterName(options, field, BYTES_DEFAULT,
|
||||
/* drop_list = */ true),
|
||||
"repeatedtag", (field->is_repeated() ? "Repeated" : ""));
|
||||
|
||||
printer->Annotate("addername", field);
|
||||
printer->Print(
|
||||
"this, $index$$oneofgroup$, opt_value, $ctor$, opt_index);\n"
|
||||
"};\n"
|
||||
|
@ -867,9 +867,7 @@ void GeneratedMessageReflection::ClearField(
|
||||
|
||||
case FieldDescriptor::CPPTYPE_MESSAGE: {
|
||||
if (IsMapFieldInApi(field)) {
|
||||
MutableRaw<MapFieldBase>(message, field)
|
||||
->MutableRepeatedField()
|
||||
->Clear<GenericTypeHandler<Message> >();
|
||||
MutableRaw<MapFieldBase>(message, field)->Clear();
|
||||
} else {
|
||||
// We don't know which subclass of RepeatedPtrFieldBase the type is,
|
||||
// so we use RepeatedPtrFieldBase directly.
|
||||
|
@ -91,21 +91,47 @@ void MapFieldBase::SetRepeatedDirty() {
|
||||
state_.store(STATE_MODIFIED_REPEATED, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void MapFieldBase::SetClean() {
|
||||
// These are called by (non-const) mutator functions. So by our API it's the
|
||||
// callers responsibility to have these calls properly ordered.
|
||||
state_.store(CLEAN, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void* MapFieldBase::MutableRepeatedPtrField() const { return repeated_field_; }
|
||||
|
||||
void MapFieldBase::SyncRepeatedFieldWithMap() const {
|
||||
// acquire here matches with release below to ensure that we can only see a
|
||||
// value of CLEAN after all previous changes have been synced.
|
||||
if (state_.load(std::memory_order_acquire) == STATE_MODIFIED_MAP) {
|
||||
mutex_.Lock();
|
||||
// Double check state, because another thread may have seen the same state
|
||||
// and done the synchronization before the current thread.
|
||||
if (state_.load(std::memory_order_relaxed) == STATE_MODIFIED_MAP) {
|
||||
SyncRepeatedFieldWithMapNoLock();
|
||||
state_.store(CLEAN, std::memory_order_release);
|
||||
switch (state_.load(std::memory_order_acquire)) {
|
||||
case STATE_MODIFIED_MAP:
|
||||
mutex_.Lock();
|
||||
// Double check state, because another thread may have seen the same
|
||||
// state and done the synchronization before the current thread.
|
||||
if (state_.load(std::memory_order_relaxed) == STATE_MODIFIED_MAP) {
|
||||
SyncRepeatedFieldWithMapNoLock();
|
||||
state_.store(CLEAN, std::memory_order_release);
|
||||
}
|
||||
mutex_.Unlock();
|
||||
break;
|
||||
case CLEAN:
|
||||
mutex_.Lock();
|
||||
// Double check state
|
||||
if (state_.load(std::memory_order_relaxed) == CLEAN) {
|
||||
if (repeated_field_ == nullptr) {
|
||||
if (arena_ == nullptr) {
|
||||
repeated_field_ = new RepeatedPtrField<Message>();
|
||||
} else {
|
||||
repeated_field_ =
|
||||
Arena::CreateMessage<RepeatedPtrField<Message> >(arena_);
|
||||
}
|
||||
}
|
||||
state_.store(CLEAN, std::memory_order_release);
|
||||
}
|
||||
mutex_.Unlock();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
mutex_.Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void MapFieldBase::SyncRepeatedFieldWithMapNoLock() const {
|
||||
@ -155,6 +181,20 @@ int DynamicMapField::size() const {
|
||||
return GetMap().size();
|
||||
}
|
||||
|
||||
void DynamicMapField::Clear() {
|
||||
Map<MapKey, MapValueRef>* map = &const_cast<DynamicMapField*>(this)->map_;
|
||||
for (Map<MapKey, MapValueRef>::iterator iter = map->begin();
|
||||
iter != map->end(); ++iter) {
|
||||
iter->second.DeleteData();
|
||||
}
|
||||
map->clear();
|
||||
|
||||
if (MapFieldBase::repeated_field_ != nullptr) {
|
||||
MapFieldBase::repeated_field_->Clear();
|
||||
}
|
||||
MapFieldBase::SetClean();
|
||||
}
|
||||
|
||||
bool DynamicMapField::ContainsMapKey(
|
||||
const MapKey& map_key) const {
|
||||
const Map<MapKey, MapValueRef>& map = GetMap();
|
||||
|
@ -107,6 +107,7 @@ class PROTOBUF_EXPORT MapFieldBase {
|
||||
virtual void Swap(MapFieldBase* other) = 0;
|
||||
// Sync Map with repeated field and returns the size of map.
|
||||
virtual int size() const = 0;
|
||||
virtual void Clear() = 0;
|
||||
|
||||
// Returns the number of bytes used by the repeated field, excluding
|
||||
// sizeof(*this)
|
||||
@ -136,6 +137,9 @@ class PROTOBUF_EXPORT MapFieldBase {
|
||||
// Tells MapFieldBase that there is new change to RepeatedPTrField.
|
||||
void SetRepeatedDirty();
|
||||
|
||||
// Tells MapFieldBase that map and repeated are the same.
|
||||
void SetClean();
|
||||
|
||||
// Provides derived class the access to repeated field.
|
||||
void* MutableRepeatedPtrField() const;
|
||||
|
||||
@ -268,9 +272,8 @@ class MapField : public TypeDefinedMapFieldBase<Key, T> {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Convenient methods for generated message implementation.
|
||||
int size() const override;
|
||||
void Clear();
|
||||
void Clear() override;
|
||||
void MergeFrom(const MapFieldBase& other) override;
|
||||
void Swap(MapFieldBase* other) override;
|
||||
|
||||
@ -334,6 +337,7 @@ class PROTOBUF_EXPORT DynamicMapField
|
||||
Map<MapKey, MapValueRef>* MutableMap() override;
|
||||
|
||||
int size() const override;
|
||||
void Clear() override;
|
||||
|
||||
private:
|
||||
Map<MapKey, MapValueRef> map_;
|
||||
|
@ -178,9 +178,15 @@ template <typename Derived, typename Key, typename T,
|
||||
WireFormatLite::FieldType kValueFieldType, int default_enum_value>
|
||||
void MapField<Derived, Key, T, kKeyFieldType, kValueFieldType,
|
||||
default_enum_value>::Clear() {
|
||||
MapFieldBase::SyncMapWithRepeatedField();
|
||||
if (this->MapFieldBase::repeated_field_ != nullptr) {
|
||||
RepeatedPtrField<EntryType>* repeated_field =
|
||||
reinterpret_cast<RepeatedPtrField<EntryType>*>(
|
||||
this->MapFieldBase::repeated_field_);
|
||||
repeated_field->Clear();
|
||||
}
|
||||
|
||||
impl_.MutableMap()->clear();
|
||||
MapFieldBase::SetMapDirty();
|
||||
MapFieldBase::SetClean();
|
||||
}
|
||||
|
||||
template <typename Derived, typename Key, typename T,
|
||||
|
@ -94,6 +94,7 @@ class MapFieldBaseStub : public MapFieldBase {
|
||||
return false;
|
||||
}
|
||||
int size() const { return 0; }
|
||||
void Clear() override {}
|
||||
void MapBegin(MapIterator* map_iter) const {}
|
||||
void MapEnd(MapIterator* map_iter) const {}
|
||||
void MergeFrom(const MapFieldBase& other) override {}
|
||||
@ -295,7 +296,11 @@ class MapFieldStateTest
|
||||
if (is_repeated_null) {
|
||||
EXPECT_TRUE(repeated_field == NULL);
|
||||
} else {
|
||||
EXPECT_EQ(repeated_size, repeated_field->size());
|
||||
if (repeated_field == nullptr) {
|
||||
EXPECT_EQ(repeated_size, 0);
|
||||
} else {
|
||||
EXPECT_EQ(repeated_size, repeated_field->size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -442,11 +447,7 @@ TEST_P(MapFieldStateTest, SwapRepeatedDirty) {
|
||||
TEST_P(MapFieldStateTest, Clear) {
|
||||
map_field_->Clear();
|
||||
|
||||
if (state_ != MAP_DIRTY) {
|
||||
Expect(map_field_.get(), MAP_DIRTY, 0, 1, false);
|
||||
} else {
|
||||
Expect(map_field_.get(), MAP_DIRTY, 0, 0, true);
|
||||
}
|
||||
Expect(map_field_.get(), CLEAN, 0, 0, false);
|
||||
}
|
||||
|
||||
TEST_P(MapFieldStateTest, SpaceUsedExcludingSelf) {
|
||||
|
@ -1582,6 +1582,10 @@ void MapReflectionTester::ExpectClearViaReflection(
|
||||
EXPECT_EQ(0, reflection->FieldSize(message, F("map_int32_bytes")));
|
||||
EXPECT_EQ(0, reflection->FieldSize(message, F("map_int32_enum")));
|
||||
EXPECT_EQ(0, reflection->FieldSize(message, F("map_int32_foreign_message")));
|
||||
EXPECT_TRUE(reflection->GetMapData(
|
||||
message, F("map_int32_foreign_message"))->IsMapValid());
|
||||
EXPECT_TRUE(reflection->GetMapData(
|
||||
message, F("map_int32_foreign_message"))->IsRepeatedFieldValid());
|
||||
}
|
||||
|
||||
void MapReflectionTester::ExpectClearViaReflectionIterator(
|
||||
|
@ -188,10 +188,10 @@ Status ProtoStreamObjectSource::WriteMessage(const google::protobuf::Type& type,
|
||||
bool include_start_and_end,
|
||||
ObjectWriter* ow) const {
|
||||
|
||||
const TypeRenderer* type_renderer = FindTypeRenderer(type.name());
|
||||
if (type_renderer != nullptr) {
|
||||
return (*type_renderer)(this, type, name, ow);
|
||||
}
|
||||
const TypeRenderer* type_renderer = FindTypeRenderer(type.name());
|
||||
if (type_renderer != nullptr) {
|
||||
return (*type_renderer)(this, type, name, ow);
|
||||
}
|
||||
|
||||
const google::protobuf::Field* field = nullptr;
|
||||
string field_name;
|
||||
@ -229,9 +229,7 @@ Status ProtoStreamObjectSource::WriteMessage(const google::protobuf::Type& type,
|
||||
|
||||
if (field->cardinality() ==
|
||||
google::protobuf::Field_Cardinality_CARDINALITY_REPEATED) {
|
||||
bool check_maps = true;
|
||||
|
||||
if (check_maps && IsMap(*field)) {
|
||||
if (IsMap(*field)) {
|
||||
ow->StartObject(field_name);
|
||||
ASSIGN_OR_RETURN(tag, RenderMap(field, field_name, tag, ow));
|
||||
ow->EndObject();
|
||||
@ -332,6 +330,7 @@ Status ProtoStreamObjectSource::RenderPacked(
|
||||
return util::Status();
|
||||
}
|
||||
|
||||
|
||||
Status ProtoStreamObjectSource::RenderTimestamp(
|
||||
const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
|
||||
StringPiece field_name, ObjectWriter* ow) {
|
||||
@ -708,6 +707,7 @@ std::unordered_map<string, ProtoStreamObjectSource::TypeRenderer>*
|
||||
ProtoStreamObjectSource::renderers_ = NULL;
|
||||
PROTOBUF_NAMESPACE_ID::internal::once_flag source_renderers_init_;
|
||||
|
||||
|
||||
void ProtoStreamObjectSource::InitRendererMap() {
|
||||
renderers_ =
|
||||
new std::unordered_map<string, ProtoStreamObjectSource::TypeRenderer>();
|
||||
@ -745,6 +745,7 @@ void ProtoStreamObjectSource::InitRendererMap() {
|
||||
::google::protobuf::internal::OnShutdown(&DeleteRendererMap);
|
||||
}
|
||||
|
||||
|
||||
void ProtoStreamObjectSource::DeleteRendererMap() {
|
||||
delete ProtoStreamObjectSource::renderers_;
|
||||
renderers_ = NULL;
|
||||
@ -781,10 +782,8 @@ Status ProtoStreamObjectSource::RenderField(
|
||||
// Short-circuit any special type rendering to save call-stack space.
|
||||
const TypeRenderer* type_renderer = FindTypeRenderer(type->name());
|
||||
|
||||
bool use_type_renderer = type_renderer != nullptr;
|
||||
|
||||
RETURN_IF_ERROR(IncrementRecursionDepth(type->name(), field_name));
|
||||
if (use_type_renderer) {
|
||||
if (type_renderer != nullptr) {
|
||||
RETURN_IF_ERROR((*type_renderer)(this, *type, field_name, ow));
|
||||
} else {
|
||||
RETURN_IF_ERROR(WriteMessage(*type, field_name, 0, true, ow));
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include <google/protobuf/stubs/status.h>
|
||||
#include <google/protobuf/stubs/statusor.h>
|
||||
|
||||
|
||||
#include <google/protobuf/port_def.inc>
|
||||
|
||||
namespace google {
|
||||
@ -181,9 +182,10 @@ class PROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource {
|
||||
// Renders a NWP map.
|
||||
// Returns the next tag after reading all map entries. The caller should use
|
||||
// this tag before reading more tags from the stream.
|
||||
util::StatusOr<uint32> RenderMap(const google::protobuf::Field* field,
|
||||
StringPiece name, uint32 list_tag,
|
||||
ObjectWriter* ow) const;
|
||||
util::StatusOr<uint32>
|
||||
RenderMap(const google::protobuf::Field* field,
|
||||
StringPiece name, uint32 list_tag,
|
||||
ObjectWriter* ow) const;
|
||||
|
||||
// Renders a packed repeating field. A packed field is stored as:
|
||||
// {tag length item1 item2 item3} instead of the less efficient
|
||||
@ -191,6 +193,7 @@ class PROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource {
|
||||
util::Status RenderPacked(const google::protobuf::Field* field,
|
||||
ObjectWriter* ow) const;
|
||||
|
||||
|
||||
// Renders a google.protobuf.Timestamp value to ObjectWriter
|
||||
static util::Status RenderTimestamp(const ProtoStreamObjectSource* os,
|
||||
const google::protobuf::Type& type,
|
||||
|
@ -118,6 +118,27 @@ class DescriptorPoolTypeResolver : public TypeResolver {
|
||||
|
||||
void ConvertMessageOptions(const MessageOptions& options,
|
||||
RepeatedPtrField<Option>* output) {
|
||||
return ConvertOptionsInternal(options, output);
|
||||
}
|
||||
|
||||
void ConvertFieldOptions(const FieldOptions& options,
|
||||
RepeatedPtrField<Option>* output) {
|
||||
return ConvertOptionsInternal(options, output);
|
||||
}
|
||||
|
||||
void ConvertEnumOptions(const EnumOptions& options,
|
||||
RepeatedPtrField<Option>* output) {
|
||||
return ConvertOptionsInternal(options, output);
|
||||
}
|
||||
|
||||
void ConvertEnumValueOptions(const EnumValueOptions& options,
|
||||
RepeatedPtrField<Option>* output) {
|
||||
return ConvertOptionsInternal(options, output);
|
||||
}
|
||||
|
||||
// Implementation details for Convert*Options.
|
||||
void ConvertOptionsInternal(const Message& options,
|
||||
RepeatedPtrField<Option>* output) {
|
||||
const Reflection* reflection = options.GetReflection();
|
||||
std::vector<const FieldDescriptor*> fields;
|
||||
reflection->ListFields(options, &fields);
|
||||
@ -125,18 +146,18 @@ class DescriptorPoolTypeResolver : public TypeResolver {
|
||||
if (field->is_repeated()) {
|
||||
const int size = reflection->FieldSize(options, field);
|
||||
for (int i = 0; i < size; i++) {
|
||||
ConvertMessageOption(reflection, options, field, i, output->Add());
|
||||
ConvertOptionField(reflection, options, field, i, output->Add());
|
||||
}
|
||||
} else {
|
||||
ConvertMessageOption(reflection, options, field, -1, output->Add());
|
||||
ConvertOptionField(reflection, options, field, -1, output->Add());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ConvertMessageOption(const Reflection* reflection,
|
||||
const MessageOptions& options,
|
||||
const FieldDescriptor* field, int index,
|
||||
Option* out) {
|
||||
static void ConvertOptionField(const Reflection* reflection,
|
||||
const Message& options,
|
||||
const FieldDescriptor* field, int index,
|
||||
Option* out) {
|
||||
out->set_name(field->is_extension() ? field->full_name() : field->name());
|
||||
Any* value = out->mutable_value();
|
||||
switch (field->cpp_type()) {
|
||||
@ -250,7 +271,7 @@ class DescriptorPoolTypeResolver : public TypeResolver {
|
||||
field->set_packed(true);
|
||||
}
|
||||
|
||||
// TODO(xiaofeng): Set other field "options"?
|
||||
ConvertFieldOptions(descriptor->options(), field->mutable_options());
|
||||
}
|
||||
|
||||
void ConvertEnumDescriptor(const EnumDescriptor* descriptor,
|
||||
@ -265,9 +286,11 @@ class DescriptorPoolTypeResolver : public TypeResolver {
|
||||
value->set_name(value_descriptor->name());
|
||||
value->set_number(value_descriptor->number());
|
||||
|
||||
// TODO(xiaofeng): Set EnumValue options.
|
||||
ConvertEnumValueOptions(value_descriptor->options(),
|
||||
value->mutable_options());
|
||||
}
|
||||
// TODO(xiaofeng): Set Enum "options".
|
||||
|
||||
ConvertEnumOptions(descriptor->options(), enum_type->mutable_options());
|
||||
}
|
||||
|
||||
string GetTypeUrl(const Descriptor* descriptor) {
|
||||
|
@ -52,10 +52,12 @@ namespace util {
|
||||
namespace {
|
||||
using google::protobuf::BoolValue;
|
||||
using google::protobuf::Enum;
|
||||
using google::protobuf::EnumValue;
|
||||
using google::protobuf::Field;
|
||||
using google::protobuf::Int32Value;
|
||||
using google::protobuf::Option;
|
||||
using google::protobuf::Type;
|
||||
using google::protobuf::UInt64Value;
|
||||
|
||||
static const char kUrlPrefix[] = "type.googleapis.com";
|
||||
|
||||
@ -117,14 +119,18 @@ class DescriptorPoolTypeResolverTest : public testing::Test {
|
||||
return field->packed();
|
||||
}
|
||||
|
||||
bool EnumHasValue(const Enum& type, const string& name, int number) {
|
||||
for (int i = 0; i < type.enumvalue_size(); ++i) {
|
||||
if (type.enumvalue(i).name() == name &&
|
||||
type.enumvalue(i).number() == number) {
|
||||
return true;
|
||||
const EnumValue* FindEnumValue(const Enum& type, const string& name) {
|
||||
for (const EnumValue& value : type.enumvalue()) {
|
||||
if (value.name() == name) {
|
||||
return &value;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool EnumHasValue(const Enum& type, const string& name, int number) {
|
||||
const EnumValue* value = FindEnumValue(type, name);
|
||||
return value != nullptr && value->number() == number;
|
||||
}
|
||||
|
||||
bool HasBoolOption(const RepeatedPtrField<Option>& options,
|
||||
@ -137,6 +143,11 @@ class DescriptorPoolTypeResolverTest : public testing::Test {
|
||||
return HasOption<Int32Value>(options, name, value);
|
||||
}
|
||||
|
||||
bool HasUInt64Option(const RepeatedPtrField<Option>& options,
|
||||
const string& name, uint64 value) {
|
||||
return HasOption<UInt64Value>(options, name, value);
|
||||
}
|
||||
|
||||
template <typename WrapperT, typename T>
|
||||
bool HasOption(const RepeatedPtrField<Option>& options, const string& name,
|
||||
T value) {
|
||||
@ -338,7 +349,7 @@ TEST_F(DescriptorPoolTypeResolverTest, TestMap) {
|
||||
EXPECT_TRUE(HasBoolOption(type.options(), "map_entry", true));
|
||||
}
|
||||
|
||||
TEST_F(DescriptorPoolTypeResolverTest, TestCustomOptions) {
|
||||
TEST_F(DescriptorPoolTypeResolverTest, TestCustomMessageOptions) {
|
||||
Type type;
|
||||
ASSERT_TRUE(
|
||||
resolver_
|
||||
@ -350,6 +361,20 @@ TEST_F(DescriptorPoolTypeResolverTest, TestCustomOptions) {
|
||||
HasInt32Option(type.options(), "protobuf_unittest.message_opt1", -56));
|
||||
}
|
||||
|
||||
TEST_F(DescriptorPoolTypeResolverTest, TestCustomFieldOptions) {
|
||||
Type type;
|
||||
ASSERT_TRUE(
|
||||
resolver_
|
||||
->ResolveMessageType(
|
||||
GetTypeUrl<protobuf_unittest::TestMessageWithCustomOptions>(),
|
||||
&type)
|
||||
.ok());
|
||||
const Field* field = FindField(type, "field1");
|
||||
ASSERT_TRUE(field != nullptr);
|
||||
EXPECT_TRUE(HasUInt64Option(field->options(), "protobuf_unittest.field_opt1",
|
||||
8765432109));
|
||||
}
|
||||
|
||||
TEST_F(DescriptorPoolTypeResolverTest, TestEnum) {
|
||||
Enum type;
|
||||
ASSERT_TRUE(resolver_->ResolveEnumType(
|
||||
@ -360,6 +385,32 @@ TEST_F(DescriptorPoolTypeResolverTest, TestEnum) {
|
||||
EnumHasValue(type, "NEG", -1);
|
||||
}
|
||||
|
||||
TEST_F(DescriptorPoolTypeResolverTest, TestCustomEnumOptions) {
|
||||
Enum type;
|
||||
ASSERT_TRUE(
|
||||
resolver_
|
||||
->ResolveEnumType(
|
||||
GetTypeUrl("protobuf_unittest.TestMessageWithCustomOptions.AnEnum"),
|
||||
&type)
|
||||
.ok());
|
||||
ASSERT_TRUE(
|
||||
HasInt32Option(type.options(), "protobuf_unittest.enum_opt1", -789));
|
||||
}
|
||||
|
||||
TEST_F(DescriptorPoolTypeResolverTest, TestCustomValueOptions) {
|
||||
Enum type;
|
||||
ASSERT_TRUE(
|
||||
resolver_
|
||||
->ResolveEnumType(
|
||||
GetTypeUrl("protobuf_unittest.TestMessageWithCustomOptions.AnEnum"),
|
||||
&type)
|
||||
.ok());
|
||||
const EnumValue* value = FindEnumValue(type, "ANENUM_VAL2");
|
||||
ASSERT_TRUE(value != nullptr);
|
||||
ASSERT_TRUE(
|
||||
HasInt32Option(value->options(), "protobuf_unittest.enum_value_opt1", 123));
|
||||
}
|
||||
|
||||
TEST_F(DescriptorPoolTypeResolverTest, TestJsonName) {
|
||||
Type type;
|
||||
ASSERT_TRUE(resolver_->ResolveMessageType(
|
||||
|
Loading…
Reference in New Issue
Block a user