diff --git a/pkg/BUILD.bazel b/pkg/BUILD.bazel index 57a39bc509..6b594e63f0 100644 --- a/pkg/BUILD.bazel +++ b/pkg/BUILD.bazel @@ -229,6 +229,7 @@ cc_dist_library( testonly = 1, tags = ["manual"], deps = [ + "//src/google/protobuf:test_textproto", "//src/google/protobuf/compiler:mock_code_generator", "//src/google/protobuf/testing", ], diff --git a/src/google/protobuf/BUILD.bazel b/src/google/protobuf/BUILD.bazel index 0de5fa0f81..9af95d63e4 100644 --- a/src/google/protobuf/BUILD.bazel +++ b/src/google/protobuf/BUILD.bazel @@ -961,6 +961,7 @@ cc_test( ":cc_test_protos", ":descriptor_legacy", ":protobuf", + ":test_textproto", "//src/google/protobuf/compiler:importer", "//src/google/protobuf/testing", "@com_google_absl//absl/log:die_if_null", @@ -971,6 +972,20 @@ cc_test( ], ) +cc_library( + name = "test_textproto", + testonly = True, + hdrs = ["test_textproto.h"], + strip_include_prefix = "/src", + visibility = ["//pkg:__pkg__"], + deps = [ + ":protobuf", + "@com_google_googletest//:gtest", + "@com_google_absl//absl/log:absl_check", + "@com_google_absl//absl/memory", + ], +) + cc_test( name = "drop_unknown_fields_test", srcs = ["drop_unknown_fields_test.cc"], diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc index 0d77da558c..e93650e2ff 100644 --- a/src/google/protobuf/descriptor.cc +++ b/src/google/protobuf/descriptor.cc @@ -57,6 +57,7 @@ #include "absl/hash/hash.h" #include "absl/log/absl_check.h" #include "absl/log/absl_log.h" +#include "absl/status/statusor.h" #include "absl/strings/ascii.h" #include "absl/strings/escaping.h" #include "absl/strings/match.h" @@ -1219,10 +1220,11 @@ class FlatAllocator : public decltype(ApplyTypeList( SortByAlignment())) {}; + ServiceOptions, MethodOptions, FileOptions>())) { +}; } // namespace internal @@ -3708,11 +3710,11 @@ namespace { // one of the Options messages in descriptor.proto. struct OptionsToInterpret { OptionsToInterpret(absl::string_view ns, absl::string_view el, - const std::vector& path, const Message* orig_opt, + absl::Span path, const Message* orig_opt, Message* opt) : name_scope(ns), element_name(el), - element_path(path), + element_path(path.begin(), path.end()), original_options(orig_opt), options(opt) {} std::string name_scope; @@ -3751,6 +3753,7 @@ class DescriptorBuilder { DescriptorPool::Tables* tables_; // for convenience DescriptorPool::ErrorCollector* error_collector_; + // As we build descriptors we store copies of the options messages in // them. We put pointers to those copies in this vector, as we build, so we // can later (after cross-linking) interpret those options. @@ -3927,22 +3930,23 @@ class DescriptorBuilder { // later. DescriptorT must be one of the Descriptor messages from // descriptor.proto. template - void AllocateOptions(const typename DescriptorT::OptionsType& orig_options, - DescriptorT* descriptor, int options_field_tag, - absl::string_view option_name, - internal::FlatAllocator& alloc); + typename DescriptorT::OptionsType* AllocateOptions( + const typename DescriptorT::Proto& proto, const DescriptorT* descriptor, + int options_field_tag, absl::string_view option_name, + internal::FlatAllocator& alloc); // Specialization for FileOptions. - void AllocateOptions(const FileOptions& orig_options, - FileDescriptor* descriptor, - internal::FlatAllocator& alloc); + FileOptions* AllocateOptions(const FileDescriptorProto& proto, + const FileDescriptor* descriptor, + internal::FlatAllocator& alloc); // Implementation for AllocateOptions(). Don't call this directly. template - void AllocateOptionsImpl( + typename DescriptorT::OptionsType* AllocateOptionsImpl( absl::string_view name_scope, absl::string_view element_name, - const typename DescriptorT::OptionsType& orig_options, - DescriptorT* descriptor, const std::vector& options_path, - absl::string_view option_name, internal::FlatAllocator& alloc); + const typename DescriptorT::Proto& proto, + absl::Span options_path, absl::string_view option_name, + internal::FlatAllocator& alloc); + // Allocates an array of two strings, the first one is a copy of `proto_name`, // and the second one is the full name. @@ -4196,15 +4200,17 @@ class DescriptorBuilder { // descriptors, which are the ones that have been interpreted. The const // proto references are passed in only so they can be provided to calls to // AddError(). Do not look at their options, which have not been interpreted. - void ValidateFileOptions(FileDescriptor* file, + void ValidateFileOptions(const FileDescriptor* file, const FileDescriptorProto& proto); - void ValidateMessageOptions(Descriptor* message, + void ValidateMessageOptions(const Descriptor* message, const DescriptorProto& proto); - void ValidateFieldOptions(FieldDescriptor* field, + void ValidateOneofOptions(const OneofDescriptor* oneof, + const OneofDescriptorProto& proto); + void ValidateFieldOptions(const FieldDescriptor* field, const FieldDescriptorProto& proto); - void ValidateEnumOptions(EnumDescriptor* enm, + void ValidateEnumOptions(const EnumDescriptor* enm, const EnumDescriptorProto& proto); - void ValidateEnumValueOptions(EnumValueDescriptor* enum_value, + void ValidateEnumValueOptions(const EnumValueDescriptor* enum_value, const EnumValueDescriptorProto& proto); void ValidateExtensionRangeOptions(const DescriptorProto& proto, const Descriptor& message); @@ -4213,20 +4219,22 @@ class DescriptorBuilder { const RepeatedPtrField& declarations, const DescriptorProto_ExtensionRange& proto, absl::flat_hash_set& full_name_set); - void ValidateServiceOptions(ServiceDescriptor* service, + void ValidateServiceOptions(const ServiceDescriptor* service, const ServiceDescriptorProto& proto); - void ValidateMethodOptions(MethodDescriptor* method, + void ValidateMethodOptions(const MethodDescriptor* method, const MethodDescriptorProto& proto); - void ValidateProto3(FileDescriptor* file, const FileDescriptorProto& proto); - void ValidateProto3Message(Descriptor* message, const DescriptorProto& proto); - void ValidateProto3Field(FieldDescriptor* field, + void ValidateProto3(const FileDescriptor* file, + const FileDescriptorProto& proto); + void ValidateProto3Message(const Descriptor* message, + const DescriptorProto& proto); + void ValidateProto3Field(const FieldDescriptor* field, const FieldDescriptorProto& proto); - void ValidateProto3Enum(EnumDescriptor* enm, + void ValidateProto3Enum(const EnumDescriptor* enm, const EnumDescriptorProto& proto); // Returns true if the map entry message is compatible with the // auto-generated entry message from map fields syntax. - bool ValidateMapEntry(FieldDescriptor* field, + bool ValidateMapEntry(const FieldDescriptor* field, const FieldDescriptorProto& proto); // Recursively detects naming conflicts with map entry types for a @@ -4234,7 +4242,7 @@ class DescriptorBuilder { void DetectMapConflicts(const Descriptor* message, const DescriptorProto& proto); - void ValidateJSType(FieldDescriptor* field, + void ValidateJSType(const FieldDescriptor* field, const FieldDescriptorProto& proto); }; @@ -4850,43 +4858,49 @@ void DescriptorBuilder::ValidateSymbolName(const std::string& name, // This generic implementation is good for all descriptors except // FileDescriptor. template -void DescriptorBuilder::AllocateOptions( - const typename DescriptorT::OptionsType& orig_options, - DescriptorT* descriptor, int options_field_tag, - absl::string_view option_name, internal::FlatAllocator& alloc) { +typename DescriptorT::OptionsType* DescriptorBuilder::AllocateOptions( + const typename DescriptorT::Proto& proto, const DescriptorT* descriptor, + int options_field_tag, absl::string_view option_name, + internal::FlatAllocator& alloc) { std::vector options_path; descriptor->GetLocationPath(&options_path); options_path.push_back(options_field_tag); - AllocateOptionsImpl(descriptor->full_name(), descriptor->full_name(), - orig_options, descriptor, options_path, option_name, - alloc); + return AllocateOptionsImpl(descriptor->full_name(), + descriptor->full_name(), proto, + options_path, option_name, alloc); } // We specialize for FileDescriptor. -void DescriptorBuilder::AllocateOptions(const FileOptions& orig_options, - FileDescriptor* descriptor, - internal::FlatAllocator& alloc) { +FileOptions* DescriptorBuilder::AllocateOptions( + const FileDescriptorProto& proto, const FileDescriptor* descriptor, + internal::FlatAllocator& alloc) { std::vector options_path; options_path.push_back(FileDescriptorProto::kOptionsFieldNumber); // We add the dummy token so that LookupSymbol does the right thing. - AllocateOptionsImpl(absl::StrCat(descriptor->package(), ".dummy"), - descriptor->name(), orig_options, descriptor, - options_path, "google.protobuf.FileOptions", alloc); + return AllocateOptionsImpl( + absl::StrCat(descriptor->package(), ".dummy"), descriptor->name(), proto, + options_path, "google.protobuf.FileOptions", alloc); } template -void DescriptorBuilder::AllocateOptionsImpl( +typename DescriptorT::OptionsType* DescriptorBuilder::AllocateOptionsImpl( absl::string_view name_scope, absl::string_view element_name, - const typename DescriptorT::OptionsType& orig_options, - DescriptorT* descriptor, const std::vector& options_path, - absl::string_view option_name, internal::FlatAllocator& alloc) { + const typename DescriptorT::Proto& proto, + absl::Span options_path, absl::string_view option_name, + internal::FlatAllocator& alloc) { + if (!proto.has_options()) { + // Set to default_instance later if necessary. + return nullptr; + } + const typename DescriptorT::OptionsType& orig_options = proto.options(); + auto* options = alloc.AllocateArray(1); if (!orig_options.IsInitialized()) { AddError(absl::StrCat(name_scope, ".", element_name), orig_options, DescriptorPool::ErrorCollector::OPTION_NAME, "Uninterpreted option is missing name or value."); - return; + return nullptr; } // Avoid using MergeFrom()/CopyFrom() in this class to make it -fno-rtti @@ -4894,7 +4908,6 @@ void DescriptorBuilder::AllocateOptionsImpl( // reflection based method, which requires the Descriptor. However, we are in // the middle of building the descriptors, thus the deadlock. options->ParseFromString(orig_options.SerializeAsString()); - descriptor->options_ = options; // Don't add to options_to_interpret_ unless there were uninterpreted // options. This not only avoids unnecessary work, but prevents a @@ -4926,8 +4939,10 @@ void DescriptorBuilder::AllocateOptionsImpl( } } } + return options; } + // A common pattern: We want to convert a repeated field in the descriptor // to an array of values, calling some method to build each value. #define BUILD_ARRAY(INPUT, OUTPUT, NAME, METHOD, PARENT) \ @@ -5211,6 +5226,7 @@ FileDescriptor* DescriptorBuilder::BuildFileImpl( FileDescriptor* result = alloc.AllocateArray(1); file_ = result; + result->is_placeholder_ = false; result->finished_building_ = false; SourceCodeInfo* info = nullptr; @@ -5310,6 +5326,7 @@ FileDescriptor* DescriptorBuilder::BuildFileImpl( return nullptr; } + if (dependency == nullptr) { if (!pool_->lazily_build_dependencies_) { if (pool_->allow_unknown_ || @@ -5420,9 +5437,9 @@ FileDescriptor* DescriptorBuilder::BuildFileImpl( BUILD_ARRAY(proto, result, extension, BuildExtension, nullptr); // Copy options. - result->options_ = nullptr; // Set to default_instance later if necessary. - if (proto.has_options()) { - AllocateOptions(proto.options(), result, alloc); + { + FileOptions* options = AllocateOptions(proto, result, alloc); + result->options_ = options; // Set to default_instance later if necessary. } // Note that the following steps must occur in exactly the specified order. @@ -5579,11 +5596,9 @@ void DescriptorBuilder::BuildMessage(const DescriptorProto& proto, } // Copy options. - if (proto.has_options()) { - AllocateOptions(proto.options(), result, - DescriptorProto::kOptionsFieldNumber, - "google.protobuf.MessageOptions", alloc); - } + result->options_ = + AllocateOptions(proto, result, DescriptorProto::kOptionsFieldNumber, + "google.protobuf.MessageOptions", alloc); AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result)); @@ -6073,12 +6088,9 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto, } // Copy options. - result->options_ = nullptr; // Set to default_instance later if necessary. - if (proto.has_options()) { - AllocateOptions(proto.options(), result, - FieldDescriptorProto::kOptionsFieldNumber, - "google.protobuf.FieldOptions", alloc); - } + result->options_ = + AllocateOptions(proto, result, FieldDescriptorProto::kOptionsFieldNumber, + "google.protobuf.FieldOptions", alloc); AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result)); } @@ -6117,9 +6129,9 @@ void DescriptorBuilder::BuildExtensionRange( } options_path.push_back(index); options_path.push_back(DescriptorProto_ExtensionRange::kOptionsFieldNumber); - AllocateOptionsImpl(parent->full_name(), parent->full_name(), - proto.options(), result, options_path, - "google.protobuf.ExtensionRangeOptions", alloc); + result->options_ = AllocateOptionsImpl( + parent->full_name(), parent->full_name(), proto, options_path, + "google.protobuf.ExtensionRangeOptions", alloc); } } @@ -6162,14 +6174,11 @@ void DescriptorBuilder::BuildOneof(const OneofDescriptorProto& proto, // We need to fill these in later. result->field_count_ = 0; result->fields_ = nullptr; - result->options_ = nullptr; // Copy options. - if (proto.has_options()) { - AllocateOptions(proto.options(), result, - OneofDescriptorProto::kOptionsFieldNumber, - "google.protobuf.OneofOptions", alloc); - } + result->options_ = + AllocateOptions(proto, result, OneofDescriptorProto::kOptionsFieldNumber, + "google.protobuf.OneofOptions", alloc); AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result)); } @@ -6292,12 +6301,9 @@ void DescriptorBuilder::BuildEnum(const EnumDescriptorProto& proto, } // Copy options. - result->options_ = nullptr; // Set to default_instance later if necessary. - if (proto.has_options()) { - AllocateOptions(proto.options(), result, - EnumDescriptorProto::kOptionsFieldNumber, - "google.protobuf.EnumOptions", alloc); - } + result->options_ = + AllocateOptions(proto, result, EnumDescriptorProto::kOptionsFieldNumber, + "google.protobuf.EnumOptions", alloc); AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result)); @@ -6373,12 +6379,9 @@ void DescriptorBuilder::BuildEnumValue(const EnumValueDescriptorProto& proto, ValidateSymbolName(proto.name(), result->full_name(), proto); // Copy options. - result->options_ = nullptr; // Set to default_instance later if necessary. - if (proto.has_options()) { - AllocateOptions(proto.options(), result, - EnumValueDescriptorProto::kOptionsFieldNumber, - "google.protobuf.EnumValueOptions", alloc); - } + result->options_ = AllocateOptions( + proto, result, EnumValueDescriptorProto::kOptionsFieldNumber, + "google.protobuf.EnumValueOptions", alloc); // Again, enum values are weird because we makes them appear as siblings // of the enum type instead of children of it. So, we use @@ -6440,12 +6443,9 @@ void DescriptorBuilder::BuildService(const ServiceDescriptorProto& proto, BUILD_ARRAY(proto, result, method, BuildMethod, result); // Copy options. - result->options_ = nullptr; // Set to default_instance later if necessary. - if (proto.has_options()) { - AllocateOptions(proto.options(), result, - ServiceDescriptorProto::kOptionsFieldNumber, - "google.protobuf.ServiceOptions", alloc); - } + result->options_ = AllocateOptions( + proto, result, ServiceDescriptorProto::kOptionsFieldNumber, + "google.protobuf.ServiceOptions", alloc); AddSymbol(result->full_name(), nullptr, result->name(), proto, Symbol(result)); @@ -6466,12 +6466,9 @@ void DescriptorBuilder::BuildMethod(const MethodDescriptorProto& proto, result->output_type_.Init(); // Copy options. - result->options_ = nullptr; // Set to default_instance later if necessary. - if (proto.has_options()) { - AllocateOptions(proto.options(), result, - MethodDescriptorProto::kOptionsFieldNumber, - "google.protobuf.MethodOptions", alloc); - } + result->options_ = + AllocateOptions(proto, result, MethodDescriptorProto::kOptionsFieldNumber, + "google.protobuf.MethodOptions", alloc); result->client_streaming_ = proto.client_streaming(); result->server_streaming_ = proto.server_streaming(); @@ -7127,7 +7124,7 @@ static bool IsLite(const FileDescriptor* file) { file->options().optimize_for() == FileOptions::LITE_RUNTIME; } -void DescriptorBuilder::ValidateFileOptions(FileDescriptor* file, +void DescriptorBuilder::ValidateFileOptions(const FileDescriptor* file, const FileDescriptorProto& proto) { VALIDATE_OPTIONS_FROM_ARRAY(file, message_type, Message); VALIDATE_OPTIONS_FROM_ARRAY(file, enum_type, Enum); @@ -7156,7 +7153,7 @@ void DescriptorBuilder::ValidateFileOptions(FileDescriptor* file, } } -void DescriptorBuilder::ValidateProto3(FileDescriptor* file, +void DescriptorBuilder::ValidateProto3(const FileDescriptor* file, const FileDescriptorProto& proto) { for (int i = 0; i < file->extension_count(); ++i) { ValidateProto3Field(file->extensions_ + i, proto.extension(i)); @@ -7169,7 +7166,7 @@ void DescriptorBuilder::ValidateProto3(FileDescriptor* file, } } -void DescriptorBuilder::ValidateProto3Message(Descriptor* message, +void DescriptorBuilder::ValidateProto3Message(const Descriptor* message, const DescriptorProto& proto) { for (int i = 0; i < message->nested_type_count(); ++i) { ValidateProto3Message(message->nested_types_ + i, proto.nested_type(i)); @@ -7195,7 +7192,7 @@ void DescriptorBuilder::ValidateProto3Message(Descriptor* message, } } -void DescriptorBuilder::ValidateProto3Field(FieldDescriptor* field, +void DescriptorBuilder::ValidateProto3Field(const FieldDescriptor* field, const FieldDescriptorProto& proto) { if (field->is_extension() && !AllowedExtendeeInProto3(field->containing_type()->full_name())) { @@ -7234,7 +7231,7 @@ void DescriptorBuilder::ValidateProto3Field(FieldDescriptor* field, } } -void DescriptorBuilder::ValidateProto3Enum(EnumDescriptor* enm, +void DescriptorBuilder::ValidateProto3Enum(const EnumDescriptor* enm, const EnumDescriptorProto& proto) { if (enm->value_count() > 0 && enm->value(0)->number() != 0) { AddError(enm->full_name(), proto.value(0), @@ -7243,7 +7240,7 @@ void DescriptorBuilder::ValidateProto3Enum(EnumDescriptor* enm, } } -void DescriptorBuilder::ValidateMessageOptions(Descriptor* message, +void DescriptorBuilder::ValidateMessageOptions(const Descriptor* message, const DescriptorProto& proto) { VALIDATE_OPTIONS_FROM_ARRAY(message, field, Field); VALIDATE_OPTIONS_FROM_ARRAY(message, nested_type, Message); @@ -7252,14 +7249,21 @@ void DescriptorBuilder::ValidateMessageOptions(Descriptor* message, CheckFieldJsonNameUniqueness(proto, message); ValidateExtensionRangeOptions(proto, *message); + for (int i = 0; i < message->real_oneof_decl_count(); ++i) { + ValidateOneofOptions(message->oneof_decl(i), proto.oneof_decl(i)); + } } +void DescriptorBuilder::ValidateOneofOptions( + const OneofDescriptor* /*oneof*/, const OneofDescriptorProto& /*proto*/) {} + void DescriptorBuilder::ValidateFieldOptions( - FieldDescriptor* field, const FieldDescriptorProto& proto) { + const FieldDescriptor* field, const FieldDescriptorProto& proto) { if (pool_->lazily_build_dependencies_ && (!field || !field->message_type())) { return; } + // Only message type fields may be lazy. if (field->options().lazy() || field->options().unverified_lazy()) { if (field->type() != FieldDescriptor::TYPE_MESSAGE) { @@ -7334,7 +7338,7 @@ void DescriptorBuilder::ValidateFieldOptions( } -void DescriptorBuilder::ValidateEnumOptions(EnumDescriptor* enm, +void DescriptorBuilder::ValidateEnumOptions(const EnumDescriptor* enm, const EnumDescriptorProto& proto) { VALIDATE_OPTIONS_FROM_ARRAY(enm, value, EnumValue); @@ -7380,7 +7384,7 @@ void DescriptorBuilder::ValidateEnumOptions(EnumDescriptor* enm, } void DescriptorBuilder::ValidateEnumValueOptions( - EnumValueDescriptor* /* enum_value */, + const EnumValueDescriptor* /* enum_value */, const EnumValueDescriptorProto& /* proto */) { // Nothing to do so far. } @@ -7521,7 +7525,7 @@ void DescriptorBuilder::ValidateExtensionRangeOptions( } void DescriptorBuilder::ValidateServiceOptions( - ServiceDescriptor* service, const ServiceDescriptorProto& proto) { + const ServiceDescriptor* service, const ServiceDescriptorProto& proto) { if (IsLite(service->file()) && (service->file()->options().cc_generic_services() || service->file()->options().java_generic_services())) { @@ -7535,11 +7539,12 @@ void DescriptorBuilder::ValidateServiceOptions( } void DescriptorBuilder::ValidateMethodOptions( - MethodDescriptor* /* method */, const MethodDescriptorProto& /* proto */) { + const MethodDescriptor* /* method */, + const MethodDescriptorProto& /* proto */) { // Nothing to do so far. } -bool DescriptorBuilder::ValidateMapEntry(FieldDescriptor* field, +bool DescriptorBuilder::ValidateMapEntry(const FieldDescriptor* field, const FieldDescriptorProto& proto) { const Descriptor* message = field->message_type(); if ( // Must not contain extensions, extension range or nested message or @@ -7675,7 +7680,7 @@ void DescriptorBuilder::DetectMapConflicts(const Descriptor* message, } } -void DescriptorBuilder::ValidateJSType(FieldDescriptor* field, +void DescriptorBuilder::ValidateJSType(const FieldDescriptor* field, const FieldDescriptorProto& proto) { FieldOptions::JSType jstype = field->options().jstype(); // The default is always acceptable. diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h index f003c3ae61..0de5864bb4 100644 --- a/src/google/protobuf/descriptor.h +++ b/src/google/protobuf/descriptor.h @@ -120,6 +120,7 @@ class ServiceOptions; class MethodOptions; class FileOptions; class UninterpretedOption; +class FeatureSet; class SourceCodeInfo; // Defined in message.h @@ -1676,6 +1677,7 @@ class PROTOBUF_EXPORT FileDescriptor : private internal::SymbolBase { const FileOptions& options() const; + private: // With the upcoming release of editions, syntax should not be used for // business logic. Instead, the various feature helpers defined in this file diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc index 23ba234a2a..39a8f1aa15 100644 --- a/src/google/protobuf/descriptor_unittest.cc +++ b/src/google/protobuf/descriptor_unittest.cc @@ -49,6 +49,7 @@ #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "google/protobuf/descriptor_legacy.h" +#include "google/protobuf/test_textproto.h" #include "google/protobuf/unittest.pb.h" #include "google/protobuf/unittest_custom_options.pb.h" #include "google/protobuf/stubs/common.h" @@ -468,7 +469,7 @@ TEST_F(FileDescriptorTest, Syntax) { proto.set_syntax("proto2"); DescriptorPool pool; const FileDescriptor* file = pool.BuildFile(proto); - EXPECT_TRUE(file != nullptr); + ASSERT_TRUE(file != nullptr); EXPECT_EQ(FileDescriptorLegacy::Syntax::SYNTAX_PROTO2, FileDescriptorLegacy(file).syntax()); FileDescriptorProto other; file->CopyTo(&other); @@ -479,7 +480,7 @@ TEST_F(FileDescriptorTest, Syntax) { proto.set_syntax("proto3"); DescriptorPool pool; const FileDescriptor* file = pool.BuildFile(proto); - EXPECT_TRUE(file != nullptr); + ASSERT_TRUE(file != nullptr); EXPECT_EQ(FileDescriptorLegacy::Syntax::SYNTAX_PROTO3, FileDescriptorLegacy(file).syntax()); FileDescriptorProto other; @@ -7074,6 +7075,7 @@ TEST_F(ValidationErrorTest, UnusedImportWithOtherError) { + TEST_F(ValidationErrorTest, PackageTooLong) { BuildFileWithErrors( "name: \"foo.proto\" " diff --git a/src/google/protobuf/test_textproto.h b/src/google/protobuf/test_textproto.h new file mode 100644 index 0000000000..c6d24cf728 --- /dev/null +++ b/src/google/protobuf/test_textproto.h @@ -0,0 +1,68 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2023 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. + +#ifndef GOOGLE_PROTOBUF_TEST_TEXTPROTO_H__ +#define GOOGLE_PROTOBUF_TEST_TEXTPROTO_H__ + +#include +#include "absl/log/absl_check.h" +#include "absl/memory/memory.h" +#include "google/protobuf/text_format.h" + +// This file contains private helpers for dealing with textprotos in our +// tests. We make no guarantees about the behavior in real-world situations, +// and these are only meant for basic unit-tests of protobuf internals. +namespace google { +namespace protobuf { + +MATCHER_P(EqualsProto, textproto, "") { + auto msg = absl::WrapUnique(arg.New()); + return TextFormat::ParseFromString(textproto, msg.get()) && + msg->DebugString() == arg.DebugString(); +} + +class ParseTextOrDie { + public: + explicit ParseTextOrDie(absl::string_view text) : text_(text) {} + template + operator Proto() { // NOLINT(google-explicit-constructor) + Proto ret; + ABSL_CHECK(TextFormat::ParseFromString(text_, &ret)); + return ret; + } + + private: + absl::string_view text_; +}; + +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_TEST_TEXTPROTO_H__