@@ -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.
@@ -8613,7 +8629,9 @@ TEST_F(FeaturesTest, OneofFieldFeaturesOverride) {
8613
8629
}
8614
8630
8615
8631
TEST_F (FeaturesTest, MapFieldFeaturesOverride) {
8616
- constexpr absl::string_view kProtoFile = R"schema(
8632
+ BuildDescriptorMessagesInTestPool ();
8633
+ BuildFileInTestPool (pb::TestFeatures::descriptor ()->file ());
8634
+ const FileDescriptor* file = ParseAndBuildFile (" foo.proto" , R"schema(
8617
8635
edition = "2023";
8618
8636
8619
8637
import "google/protobuf/unittest_features.proto";
@@ -8630,22 +8648,7 @@ TEST_F(FeaturesTest, MapFieldFeaturesOverride) {
8630
8648
features.(pb.test).multiple_feature = VALUE3
8631
8649
];
8632
8650
}
8633
- )schema" ;
8634
- io::ArrayInputStream input_stream (kProtoFile .data (), kProtoFile .size ());
8635
- SimpleErrorCollector error_collector;
8636
- io::Tokenizer tokenizer (&input_stream, &error_collector);
8637
- compiler::Parser parser;
8638
- parser.RecordErrorsTo (&error_collector);
8639
- FileDescriptorProto proto;
8640
- ASSERT_TRUE (parser.Parse (&tokenizer, &proto))
8641
- << error_collector.last_error () << " \n "
8642
- << kProtoFile ;
8643
- ASSERT_EQ (" " , error_collector.last_error ());
8644
- proto.set_name (" foo.proto" );
8645
-
8646
- BuildDescriptorMessagesInTestPool ();
8647
- BuildFileInTestPool (pb::TestFeatures::descriptor ()->file ());
8648
- const FileDescriptor* file = pool_.BuildFile (proto);
8651
+ )schema" );
8649
8652
ASSERT_THAT (file, NotNull ());
8650
8653
8651
8654
const FieldDescriptor* map_field = file->message_type (0 )->field (0 );
@@ -8673,7 +8676,8 @@ TEST_F(FeaturesTest, MapFieldFeaturesOverride) {
8673
8676
}
8674
8677
8675
8678
TEST_F (FeaturesTest, MapFieldFeaturesStringValidation) {
8676
- constexpr absl::string_view kProtoFile = R"schema(
8679
+ BuildDescriptorMessagesInTestPool ();
8680
+ const FileDescriptor* file = ParseAndBuildFile (" foo.proto" , R"schema(
8677
8681
edition = "2023";
8678
8682
8679
8683
message Foo {
@@ -8687,21 +8691,7 @@ TEST_F(FeaturesTest, MapFieldFeaturesStringValidation) {
8687
8691
features.utf8_validation = NONE
8688
8692
];
8689
8693
}
8690
- )schema" ;
8691
- io::ArrayInputStream input_stream (kProtoFile .data (), kProtoFile .size ());
8692
- SimpleErrorCollector error_collector;
8693
- io::Tokenizer tokenizer (&input_stream, &error_collector);
8694
- compiler::Parser parser;
8695
- parser.RecordErrorsTo (&error_collector);
8696
- FileDescriptorProto proto;
8697
- ASSERT_TRUE (parser.Parse (&tokenizer, &proto))
8698
- << error_collector.last_error () << " \n "
8699
- << kProtoFile ;
8700
- ASSERT_EQ (" " , error_collector.last_error ());
8701
- proto.set_name (" foo.proto" );
8702
-
8703
- BuildDescriptorMessagesInTestPool ();
8704
- const FileDescriptor* file = pool_.BuildFile (proto);
8694
+ )schema" );
8705
8695
ASSERT_THAT (file, NotNull ());
8706
8696
8707
8697
auto validate_map_field = [](const FieldDescriptor* field) {
@@ -8718,6 +8708,109 @@ TEST_F(FeaturesTest, MapFieldFeaturesStringValidation) {
8718
8708
validate_map_field (file->message_type (0 )->field (2 ));
8719
8709
}
8720
8710
8711
+ TEST_F (FeaturesTest, MapFieldFeaturesImplicitPresence) {
8712
+ BuildDescriptorMessagesInTestPool ();
8713
+ const FileDescriptor* editions = ParseAndBuildFile (" editions.proto" , R"schema(
8714
+ edition = "2023";
8715
+
8716
+ option features.field_presence = IMPLICIT;
8717
+
8718
+ message Foo {
8719
+ map<string, Foo> message_map = 1;
8720
+ map<string, string> string_map = 2;
8721
+ }
8722
+ )schema" );
8723
+ ASSERT_THAT (editions, NotNull ());
8724
+ const FileDescriptor* proto3 = ParseAndBuildFile (" proto3.proto" , R"schema(
8725
+ syntax = "proto3";
8726
+
8727
+ message Bar {
8728
+ map<string, Bar> message_map = 1;
8729
+ map<string, string> string_map = 2;
8730
+ }
8731
+ )schema" );
8732
+ ASSERT_THAT (proto3, NotNull ());
8733
+
8734
+ auto validate_maps = [](const FileDescriptor* file) {
8735
+ const FieldDescriptor* message_map = file->message_type (0 )->field (0 );
8736
+ EXPECT_FALSE (message_map->has_presence ());
8737
+ EXPECT_FALSE (message_map->message_type ()->field (0 )->has_presence ());
8738
+ EXPECT_TRUE (message_map->message_type ()->field (1 )->has_presence ());
8739
+
8740
+ const FieldDescriptor* string_map = file->message_type (0 )->field (1 );
8741
+ EXPECT_FALSE (string_map->has_presence ());
8742
+ EXPECT_FALSE (string_map->message_type ()->field (0 )->has_presence ());
8743
+ EXPECT_FALSE (string_map->message_type ()->field (1 )->has_presence ());
8744
+ };
8745
+ validate_maps (editions);
8746
+ validate_maps (proto3);
8747
+ }
8748
+
8749
+ TEST_F (FeaturesTest, MapFieldFeaturesExplicitPresence) {
8750
+ BuildDescriptorMessagesInTestPool ();
8751
+ const FileDescriptor* editions = ParseAndBuildFile (" editions.proto" , R"schema(
8752
+ edition = "2023";
8753
+
8754
+ message Foo {
8755
+ map<string, Foo> message_map = 1;
8756
+ map<string, string> string_map = 2;
8757
+ }
8758
+ )schema" );
8759
+ ASSERT_THAT (editions, NotNull ());
8760
+ const FileDescriptor* proto2 = ParseAndBuildFile (" google.protobuf.proto" , R"schema(
8761
+ syntax = "proto2";
8762
+
8763
+ message Bar {
8764
+ map<string, Bar> message_map = 1;
8765
+ map<string, string> string_map = 2;
8766
+ }
8767
+ )schema" );
8768
+ ASSERT_THAT (proto2, NotNull ());
8769
+
8770
+ auto validate_maps = [](const FileDescriptor* file) {
8771
+ const FieldDescriptor* message_map = file->message_type (0 )->field (0 );
8772
+ EXPECT_FALSE (message_map->has_presence ());
8773
+ EXPECT_TRUE (message_map->message_type ()->field (0 )->has_presence ());
8774
+ EXPECT_TRUE (message_map->message_type ()->field (1 )->has_presence ());
8775
+
8776
+ const FieldDescriptor* string_map = file->message_type (0 )->field (1 );
8777
+ EXPECT_FALSE (string_map->has_presence ());
8778
+ EXPECT_TRUE (string_map->message_type ()->field (0 )->has_presence ());
8779
+ EXPECT_TRUE (string_map->message_type ()->field (1 )->has_presence ());
8780
+ };
8781
+ validate_maps (editions);
8782
+ validate_maps (proto2);
8783
+ }
8784
+
8785
+ TEST_F (FeaturesTest, MapFieldFeaturesInheritedMessageEncoding) {
8786
+ BuildDescriptorMessagesInTestPool ();
8787
+ const FileDescriptor* file = ParseAndBuildFile (" foo.proto" , R"schema(
8788
+ edition = "2023";
8789
+
8790
+ option features.message_encoding = DELIMITED;
8791
+
8792
+ message Foo {
8793
+ map<int32, Foo> message_map = 1;
8794
+ map<string, string> string_map = 2;
8795
+ }
8796
+ )schema" );
8797
+ ASSERT_THAT (file, NotNull ());
8798
+
8799
+ const FieldDescriptor* message_map = file->message_type (0 )->field (0 );
8800
+ EXPECT_EQ (message_map->type (), FieldDescriptor::TYPE_MESSAGE);
8801
+ EXPECT_EQ (message_map->message_type ()->field (0 )->type (),
8802
+ FieldDescriptor::TYPE_INT32);
8803
+ EXPECT_EQ (message_map->message_type ()->field (1 )->type (),
8804
+ FieldDescriptor::TYPE_MESSAGE);
8805
+
8806
+ const FieldDescriptor* string_map = file->message_type (0 )->field (1 );
8807
+ EXPECT_EQ (string_map->type (), FieldDescriptor::TYPE_MESSAGE);
8808
+ EXPECT_EQ (string_map->message_type ()->field (0 )->type (),
8809
+ FieldDescriptor::TYPE_STRING);
8810
+ EXPECT_EQ (string_map->message_type ()->field (1 )->type (),
8811
+ FieldDescriptor::TYPE_STRING);
8812
+ }
8813
+
8721
8814
TEST_F (FeaturesTest, RootExtensionFeaturesOverride) {
8722
8815
BuildDescriptorMessagesInTestPool ();
8723
8816
BuildFileInTestPool (pb::TestFeatures::descriptor ()->file ());
0 commit comments