@@ -4059,6 +4059,22 @@ class ValidationErrorTest : public testing::Test {
4059
4059
return ABSL_DIE_IF_NULL (pool_.BuildFile (file_proto));
4060
4060
}
4061
4061
4062
+ const FileDescriptor* ParseAndBuildFile (absl::string_view file_name,
4063
+ absl::string_view file_text) {
4064
+ io::ArrayInputStream input_stream (file_text.data (), file_text.size ());
4065
+ SimpleErrorCollector error_collector;
4066
+ io::Tokenizer tokenizer (&input_stream, &error_collector);
4067
+ compiler::Parser parser;
4068
+ parser.RecordErrorsTo (&error_collector);
4069
+ FileDescriptorProto proto;
4070
+ ABSL_CHECK (parser.Parse (&tokenizer, &proto))
4071
+ << error_collector.last_error () << " \n "
4072
+ << file_text;
4073
+ ABSL_CHECK_EQ (" " , error_collector.last_error ());
4074
+ proto.set_name (file_name);
4075
+ return pool_.BuildFile (proto);
4076
+ }
4077
+
4062
4078
4063
4079
// Add file_proto to the DescriptorPool. Expect errors to be produced which
4064
4080
// match the given error text.
@@ -8684,7 +8700,9 @@ TEST_F(FeaturesTest, OneofFieldFeaturesOverride) {
8684
8700
}
8685
8701
8686
8702
TEST_F (FeaturesTest, MapFieldFeaturesOverride) {
8687
- constexpr absl::string_view kProtoFile = R"schema(
8703
+ BuildDescriptorMessagesInTestPool ();
8704
+ BuildFileInTestPool (pb::TestFeatures::descriptor ()->file ());
8705
+ const FileDescriptor* file = ParseAndBuildFile (" foo.proto" , R"schema(
8688
8706
edition = "2023";
8689
8707
8690
8708
import "google/protobuf/unittest_features.proto";
@@ -8701,22 +8719,7 @@ TEST_F(FeaturesTest, MapFieldFeaturesOverride) {
8701
8719
features.(pb.test).multiple_feature = VALUE3
8702
8720
];
8703
8721
}
8704
- )schema" ;
8705
- io::ArrayInputStream input_stream (kProtoFile .data (), kProtoFile .size ());
8706
- SimpleErrorCollector error_collector;
8707
- io::Tokenizer tokenizer (&input_stream, &error_collector);
8708
- compiler::Parser parser;
8709
- parser.RecordErrorsTo (&error_collector);
8710
- FileDescriptorProto proto;
8711
- ASSERT_TRUE (parser.Parse (&tokenizer, &proto))
8712
- << error_collector.last_error () << " \n "
8713
- << kProtoFile ;
8714
- ASSERT_EQ (" " , error_collector.last_error ());
8715
- proto.set_name (" foo.proto" );
8716
-
8717
- BuildDescriptorMessagesInTestPool ();
8718
- BuildFileInTestPool (pb::TestFeatures::descriptor ()->file ());
8719
- const FileDescriptor* file = pool_.BuildFile (proto);
8722
+ )schema" );
8720
8723
ASSERT_THAT (file, NotNull ());
8721
8724
8722
8725
const FieldDescriptor* map_field = file->message_type (0 )->field (0 );
@@ -8744,7 +8747,8 @@ TEST_F(FeaturesTest, MapFieldFeaturesOverride) {
8744
8747
}
8745
8748
8746
8749
TEST_F (FeaturesTest, MapFieldFeaturesStringValidation) {
8747
- constexpr absl::string_view kProtoFile = R"schema(
8750
+ BuildDescriptorMessagesInTestPool ();
8751
+ const FileDescriptor* file = ParseAndBuildFile (" foo.proto" , R"schema(
8748
8752
edition = "2023";
8749
8753
8750
8754
message Foo {
@@ -8758,21 +8762,7 @@ TEST_F(FeaturesTest, MapFieldFeaturesStringValidation) {
8758
8762
features.utf8_validation = NONE
8759
8763
];
8760
8764
}
8761
- )schema" ;
8762
- io::ArrayInputStream input_stream (kProtoFile .data (), kProtoFile .size ());
8763
- SimpleErrorCollector error_collector;
8764
- io::Tokenizer tokenizer (&input_stream, &error_collector);
8765
- compiler::Parser parser;
8766
- parser.RecordErrorsTo (&error_collector);
8767
- FileDescriptorProto proto;
8768
- ASSERT_TRUE (parser.Parse (&tokenizer, &proto))
8769
- << error_collector.last_error () << " \n "
8770
- << kProtoFile ;
8771
- ASSERT_EQ (" " , error_collector.last_error ());
8772
- proto.set_name (" foo.proto" );
8773
-
8774
- BuildDescriptorMessagesInTestPool ();
8775
- const FileDescriptor* file = pool_.BuildFile (proto);
8765
+ )schema" );
8776
8766
ASSERT_THAT (file, NotNull ());
8777
8767
8778
8768
auto validate_map_field = [](const FieldDescriptor* field) {
@@ -8789,6 +8779,109 @@ TEST_F(FeaturesTest, MapFieldFeaturesStringValidation) {
8789
8779
validate_map_field (file->message_type (0 )->field (2 ));
8790
8780
}
8791
8781
8782
+ TEST_F (FeaturesTest, MapFieldFeaturesImplicitPresence) {
8783
+ BuildDescriptorMessagesInTestPool ();
8784
+ const FileDescriptor* editions = ParseAndBuildFile (" editions.proto" , R"schema(
8785
+ edition = "2023";
8786
+
8787
+ option features.field_presence = IMPLICIT;
8788
+
8789
+ message Foo {
8790
+ map<string, Foo> message_map = 1;
8791
+ map<string, string> string_map = 2;
8792
+ }
8793
+ )schema" );
8794
+ ASSERT_THAT (editions, NotNull ());
8795
+ const FileDescriptor* proto3 = ParseAndBuildFile (" proto3.proto" , R"schema(
8796
+ syntax = "proto3";
8797
+
8798
+ message Bar {
8799
+ map<string, Bar> message_map = 1;
8800
+ map<string, string> string_map = 2;
8801
+ }
8802
+ )schema" );
8803
+ ASSERT_THAT (proto3, NotNull ());
8804
+
8805
+ auto validate_maps = [](const FileDescriptor* file) {
8806
+ const FieldDescriptor* message_map = file->message_type (0 )->field (0 );
8807
+ EXPECT_FALSE (message_map->has_presence ());
8808
+ EXPECT_FALSE (message_map->message_type ()->field (0 )->has_presence ());
8809
+ EXPECT_TRUE (message_map->message_type ()->field (1 )->has_presence ());
8810
+
8811
+ const FieldDescriptor* string_map = file->message_type (0 )->field (1 );
8812
+ EXPECT_FALSE (string_map->has_presence ());
8813
+ EXPECT_FALSE (string_map->message_type ()->field (0 )->has_presence ());
8814
+ EXPECT_FALSE (string_map->message_type ()->field (1 )->has_presence ());
8815
+ };
8816
+ validate_maps (editions);
8817
+ validate_maps (proto3);
8818
+ }
8819
+
8820
+ TEST_F (FeaturesTest, MapFieldFeaturesExplicitPresence) {
8821
+ BuildDescriptorMessagesInTestPool ();
8822
+ const FileDescriptor* editions = ParseAndBuildFile (" editions.proto" , R"schema(
8823
+ edition = "2023";
8824
+
8825
+ message Foo {
8826
+ map<string, Foo> message_map = 1;
8827
+ map<string, string> string_map = 2;
8828
+ }
8829
+ )schema" );
8830
+ ASSERT_THAT (editions, NotNull ());
8831
+ const FileDescriptor* proto2 = ParseAndBuildFile (" google.protobuf.proto" , R"schema(
8832
+ syntax = "proto2";
8833
+
8834
+ message Bar {
8835
+ map<string, Bar> message_map = 1;
8836
+ map<string, string> string_map = 2;
8837
+ }
8838
+ )schema" );
8839
+ ASSERT_THAT (proto2, NotNull ());
8840
+
8841
+ auto validate_maps = [](const FileDescriptor* file) {
8842
+ const FieldDescriptor* message_map = file->message_type (0 )->field (0 );
8843
+ EXPECT_FALSE (message_map->has_presence ());
8844
+ EXPECT_TRUE (message_map->message_type ()->field (0 )->has_presence ());
8845
+ EXPECT_TRUE (message_map->message_type ()->field (1 )->has_presence ());
8846
+
8847
+ const FieldDescriptor* string_map = file->message_type (0 )->field (1 );
8848
+ EXPECT_FALSE (string_map->has_presence ());
8849
+ EXPECT_TRUE (string_map->message_type ()->field (0 )->has_presence ());
8850
+ EXPECT_TRUE (string_map->message_type ()->field (1 )->has_presence ());
8851
+ };
8852
+ validate_maps (editions);
8853
+ validate_maps (proto2);
8854
+ }
8855
+
8856
+ TEST_F (FeaturesTest, MapFieldFeaturesInheritedMessageEncoding) {
8857
+ BuildDescriptorMessagesInTestPool ();
8858
+ const FileDescriptor* file = ParseAndBuildFile (" foo.proto" , R"schema(
8859
+ edition = "2023";
8860
+
8861
+ option features.message_encoding = DELIMITED;
8862
+
8863
+ message Foo {
8864
+ map<int32, Foo> message_map = 1;
8865
+ map<string, string> string_map = 2;
8866
+ }
8867
+ )schema" );
8868
+ ASSERT_THAT (file, NotNull ());
8869
+
8870
+ const FieldDescriptor* message_map = file->message_type (0 )->field (0 );
8871
+ EXPECT_EQ (message_map->type (), FieldDescriptor::TYPE_MESSAGE);
8872
+ EXPECT_EQ (message_map->message_type ()->field (0 )->type (),
8873
+ FieldDescriptor::TYPE_INT32);
8874
+ EXPECT_EQ (message_map->message_type ()->field (1 )->type (),
8875
+ FieldDescriptor::TYPE_MESSAGE);
8876
+
8877
+ const FieldDescriptor* string_map = file->message_type (0 )->field (1 );
8878
+ EXPECT_EQ (string_map->type (), FieldDescriptor::TYPE_MESSAGE);
8879
+ EXPECT_EQ (string_map->message_type ()->field (0 )->type (),
8880
+ FieldDescriptor::TYPE_STRING);
8881
+ EXPECT_EQ (string_map->message_type ()->field (1 )->type (),
8882
+ FieldDescriptor::TYPE_STRING);
8883
+ }
8884
+
8792
8885
TEST_F (FeaturesTest, RootExtensionFeaturesOverride) {
8793
8886
BuildDescriptorMessagesInTestPool ();
8794
8887
BuildFileInTestPool (pb::TestFeatures::descriptor ()->file ());
0 commit comments