@@ -4059,8 +4059,8 @@ class ValidationErrorTest : public testing::Test {
40594059 return ABSL_DIE_IF_NULL (pool_.BuildFile (file_proto));
40604060 }
40614061
4062- const FileDescriptor* ParseAndBuildFile (absl::string_view file_name,
4063- absl::string_view file_text) {
4062+ FileDescriptorProto ParseFile (absl::string_view file_name,
4063+ absl::string_view file_text) {
40644064 io::ArrayInputStream input_stream (file_text.data (), file_text.size ());
40654065 SimpleErrorCollector error_collector;
40664066 io::Tokenizer tokenizer (&input_stream, &error_collector);
@@ -4072,7 +4072,12 @@ class ValidationErrorTest : public testing::Test {
40724072 << file_text;
40734073 ABSL_CHECK_EQ (" " , error_collector.last_error ());
40744074 proto.set_name (file_name);
4075- return pool_.BuildFile (proto);
4075+ return proto;
4076+ }
4077+
4078+ const FileDescriptor* ParseAndBuildFile (absl::string_view file_name,
4079+ absl::string_view file_text) {
4080+ return pool_.BuildFile (ParseFile (file_name, file_text));
40764081 }
40774082
40784083
@@ -4096,6 +4101,17 @@ class ValidationErrorTest : public testing::Test {
40964101 BuildFileWithErrors (file_proto, expected_errors);
40974102 }
40984103
4104+ // Parse a proto file and build it. Expect errors to be produced which match
4105+ // the given error text.
4106+ void ParseAndBuildFileWithErrors (absl::string_view file_name,
4107+ absl::string_view file_text,
4108+ absl::string_view expected_errors) {
4109+ MockErrorCollector error_collector;
4110+ EXPECT_TRUE (pool_.BuildFileCollectingErrors (ParseFile (file_name, file_text),
4111+ &error_collector) == nullptr );
4112+ EXPECT_EQ (expected_errors, error_collector.text_ );
4113+ }
4114+
40994115 // Parse file_text as a FileDescriptorProto in text format and add it
41004116 // to the DescriptorPool. Expect errors to be produced which match the
41014117 // given warning text.
@@ -10283,6 +10299,44 @@ TEST_F(FeaturesTest, InvalidOpenEnumNonZeroFirstValue) {
1028310299 " enums.\n " );
1028410300}
1028510301
10302+ TEST_F (FeaturesTest, InvalidUseFeaturesInSameFile) {
10303+ BuildDescriptorMessagesInTestPool ();
10304+ ParseAndBuildFileWithErrors (" foo.proto" , R"schema(
10305+ edition = "2023";
10306+
10307+ package test;
10308+ import "google/protobuf/descriptor.proto";
10309+
10310+ message Foo {
10311+ string bar = 1 [
10312+ features.(test.custom).foo = "xyz",
10313+ features.(test.another) = {foo: -321}
10314+ ];
10315+ }
10316+
10317+ message Custom {
10318+ string foo = 1 [features = { [test.custom]: {foo: "abc"} }];
10319+ }
10320+ message Another {
10321+ Enum foo = 1;
10322+ }
10323+
10324+ enum Enum {
10325+ option features.enum_type = CLOSED;
10326+ ZERO = 0;
10327+ ONE = 1;
10328+ }
10329+
10330+ extend google.protobuf.FeatureSet {
10331+ Custom custom = 1002 [features.message_encoding=DELIMITED];
10332+ Another another = 1001;
10333+ }
10334+ )schema" ,
10335+ " foo.proto: test.Foo.bar: OPTION_NAME: Feature "
10336+ " \" features.(test.custom)\" can't be used in the "
10337+ " same file it's defined in.\n " );
10338+ }
10339+
1028610340TEST_F (FeaturesTest, ClosedEnumNonZeroFirstValue) {
1028710341 BuildDescriptorMessagesInTestPool ();
1028810342 const FileDescriptor* file = BuildFile (
0 commit comments