Sync from Piper @464784061 PROTOBUF_SYNC_PIPER
diff --git a/cmake/extract_includes.bat.in b/cmake/extract_includes.bat.in new file mode 100644 index 0000000..1292829 --- /dev/null +++ b/cmake/extract_includes.bat.in
@@ -0,0 +1,144 @@ +mkdir include +mkdir include\google +mkdir include\google\protobuf +mkdir include\google\protobuf\compiler +mkdir include\google\protobuf\compiler\cpp +mkdir include\google\protobuf\compiler\csharp +mkdir include\google\protobuf\compiler\java +mkdir include\google\protobuf\compiler\objectivec +mkdir include\google\protobuf\compiler\php +mkdir include\google\protobuf\compiler\python +mkdir include\google\protobuf\compiler\ruby +mkdir include\google\protobuf\io +mkdir include\google\protobuf\stubs +mkdir include\google\protobuf\util +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\any.h" include\google\protobuf\any.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\any.pb.h" include\google\protobuf\any.pb.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\api.pb.h" include\google\protobuf\api.pb.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\arena.h" include\google\protobuf\arena.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\arena_impl.h" include\google\protobuf\arena_impl.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\arenastring.h" include\google\protobuf\arenastring.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\arenaz_sampler.h" include\google\protobuf\arenaz_sampler.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\code_generator.h" include\google\protobuf\compiler\code_generator.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\command_line_interface.h" include\google\protobuf\compiler\command_line_interface.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\cpp\file.h" include\google\protobuf\compiler\cpp\file.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\cpp\cpp_generator.h" include\google\protobuf\compiler\cpp\cpp_generator.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\cpp\generator.h" include\google\protobuf\compiler\cpp\generator.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\cpp\helpers.h" include\google\protobuf\compiler\cpp\helpers.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\cpp\names.h" include\google\protobuf\compiler\cpp\names.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\csharp\csharp_doc_comment.h" include\google\protobuf\compiler\csharp\csharp_doc_comment.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\csharp\csharp_generator.h" include\google\protobuf\compiler\csharp\csharp_generator.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\csharp\csharp_names.h" include\google\protobuf\compiler\csharp\csharp_names.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\csharp\csharp_options.h" include\google\protobuf\compiler\csharp\csharp_options.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\importer.h" include\google\protobuf\compiler\importer.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\java\generator.h" include\google\protobuf\compiler\java\generator.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\java\java_generator.h" include\google\protobuf\compiler\java\java_generator.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\java\kotlin_generator.h" include\google\protobuf\compiler\java\kotlin_generator.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\java\names.h" include\google\protobuf\compiler\java\names.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\objectivec\objectivec_generator.h" include\google\protobuf\compiler\objectivec\objectivec_generator.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\objectivec\objectivec_helpers.h" include\google\protobuf\compiler\objectivec\objectivec_helpers.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\parser.h" include\google\protobuf\compiler\parser.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\php\php_generator.h" include\google\protobuf\compiler\php\php_generator.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\plugin.h" include\google\protobuf\compiler\plugin.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\plugin.pb.h" include\google\protobuf\compiler\plugin.pb.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\python\generator.h" include\google\protobuf\compiler\python\generator.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\python\pyi_generator.h" include\google\protobuf\compiler\python\pyi_generator.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\python\python_generator.h" include\google\protobuf\compiler\python\python_generator.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\ruby\ruby_generator.h" include\google\protobuf\compiler\ruby\ruby_generator.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\descriptor.h" include\google\protobuf\descriptor.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\descriptor.pb.h" include\google\protobuf\descriptor.pb.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\descriptor_database.h" include\google\protobuf\descriptor_database.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\duration.pb.h" include\google\protobuf\duration.pb.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\dynamic_message.h" include\google\protobuf\dynamic_message.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\empty.pb.h" include\google\protobuf\empty.pb.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\endian.h" include\google\protobuf\endian.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\explicitly_constructed.h" include\google\protobuf\explicitly_constructed.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\extension_set.h" include\google\protobuf\extension_set.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\extension_set_inl.h" include\google\protobuf\extension_set_inl.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\field_access_listener.h" include\google\protobuf\field_access_listener.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\field_mask.pb.h" include\google\protobuf\field_mask.pb.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_enum_reflection.h" include\google\protobuf\generated_enum_reflection.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_enum_util.h" include\google\protobuf\generated_enum_util.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_bases.h" include\google\protobuf\generated_message_bases.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_reflection.h" include\google\protobuf\generated_message_reflection.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_tctable_decl.h" include\google\protobuf\generated_message_tctable_decl.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_tctable_impl.h" include\google\protobuf\generated_message_tctable_impl.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\generated_message_util.h" include\google\protobuf\generated_message_util.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\has_bits.h" include\google\protobuf\has_bits.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\implicit_weak_message.h" include\google\protobuf\implicit_weak_message.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\inlined_string_field.h" include\google\protobuf\inlined_string_field.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\coded_stream.h" include\google\protobuf\io\coded_stream.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\gzip_stream.h" include\google\protobuf\io\gzip_stream.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\io_win32.h" include\google\protobuf\io\io_win32.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\printer.h" include\google\protobuf\io\printer.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\strtod.h" include\google\protobuf\io\strtod.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\tokenizer.h" include\google\protobuf\io\tokenizer.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\zero_copy_stream.h" include\google\protobuf\io\zero_copy_stream.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\zero_copy_stream_impl.h" include\google\protobuf\io\zero_copy_stream_impl.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\zero_copy_stream_impl_lite.h" include\google\protobuf\io\zero_copy_stream_impl_lite.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map.h" include\google\protobuf\map.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map_entry.h" include\google\protobuf\map_entry.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map_entry_lite.h" include\google\protobuf\map_entry_lite.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map_field.h" include\google\protobuf\map_field.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map_field_inl.h" include\google\protobuf\map_field_inl.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map_field_lite.h" include\google\protobuf\map_field_lite.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map_type_handler.h" include\google\protobuf\map_type_handler.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\message.h" include\google\protobuf\message.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\message_lite.h" include\google\protobuf\message_lite.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\metadata.h" include\google\protobuf\metadata.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\metadata_lite.h" include\google\protobuf\metadata_lite.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\parse_context.h" include\google\protobuf\parse_context.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\port.h" include\google\protobuf\port.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\port_def.inc" include\google\protobuf\port_def.inc +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\port_undef.inc" include\google\protobuf\port_undef.inc +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\reflection.h" include\google\protobuf\reflection.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\reflection_ops.h" include\google\protobuf\reflection_ops.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\repeated_field.h" include\google\protobuf\repeated_field.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\repeated_ptr_field.h" include\google\protobuf\repeated_ptr_field.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\service.h" include\google\protobuf\service.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\source_context.pb.h" include\google\protobuf\source_context.pb.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\struct.pb.h" include\google\protobuf\struct.pb.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\bytestream.h" include\google\protobuf\stubs\bytestream.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\callback.h" include\google\protobuf\stubs\callback.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\casts.h" include\google\protobuf\stubs\casts.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\common.h" include\google\protobuf\stubs\common.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\hash.h" include\google\protobuf\stubs\hash.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\logging.h" include\google\protobuf\stubs\logging.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\macros.h" include\google\protobuf\stubs\macros.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\map_util.h" include\google\protobuf\stubs\map_util.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\mutex.h" include\google\protobuf\stubs\mutex.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\once.h" include\google\protobuf\stubs\once.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\platform_macros.h" include\google\protobuf\stubs\platform_macros.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\port.h" include\google\protobuf\stubs\port.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\status.h" include\google\protobuf\stubs\status.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\stl_util.h" include\google\protobuf\stubs\stl_util.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\stringpiece.h" include\google\protobuf\stubs\stringpiece.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\strutil.h" include\google\protobuf\stubs\strutil.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\template_util.h" include\google\protobuf\stubs\template_util.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\text_format.h" include\google\protobuf\text_format.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\timestamp.pb.h" include\google\protobuf\timestamp.pb.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\type.pb.h" include\google\protobuf\type.pb.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\unknown_field_set.h" include\google\protobuf\unknown_field_set.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\delimited_message_util.h" include\google\protobuf\util\delimited_message_util.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\field_comparator.h" include\google\protobuf\util\field_comparator.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\field_mask_util.h" include\google\protobuf\util\field_mask_util.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\json_util.h" include\google\protobuf\util\json_util.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\message_differencer.h" include\google\protobuf\util\message_differencer.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\time_util.h" include\google\protobuf\util\time_util.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\type_resolver.h" include\google\protobuf\util\type_resolver.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\type_resolver_util.h" include\google\protobuf\util\type_resolver_util.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\wire_format.h" include\google\protobuf\wire_format.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\wire_format_lite.h" include\google\protobuf\wire_format_lite.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\wrappers.pb.h" include\google\protobuf\wrappers.pb.h +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\any.proto" include\google\protobuf\any.proto +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\api.proto" include\google\protobuf\api.proto +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\plugin.proto" include\google\protobuf\compiler\plugin.proto +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\descriptor.proto" include\google\protobuf\descriptor.proto +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\duration.proto" include\google\protobuf\duration.proto +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\empty.proto" include\google\protobuf\empty.proto +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\field_mask.proto" include\google\protobuf\field_mask.proto +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\source_context.proto" include\google\protobuf\source_context.proto +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\struct.proto" include\google\protobuf\struct.proto +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\timestamp.proto" include\google\protobuf\timestamp.proto +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\type.proto" include\google\protobuf\type.proto +copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\wrappers.proto" include\google\protobuf\wrappers.proto
diff --git a/cmake/tests.cmake b/cmake/tests.cmake index ce2a890..6a1d1c0 100644 --- a/cmake/tests.cmake +++ b/cmake/tests.cmake
@@ -130,7 +130,7 @@ /wd4146 # unary minus operator applied to unsigned type, result still unsigned ) endif() -target_link_libraries(tests protobuf-lite-test-common protobuf-test-common ${protobuf_LIB_PROTOC} ${protobuf_LIB_PROTOBUF_LITE} GTest::gmock_main) +target_link_libraries(tests protobuf-lite-test-common protobuf-test-common ${protobuf_LIB_PROTOC} ${protobuf_LIB_PROTOBUF} GTest::gmock_main) set(test_plugin_files ${test_plugin_files}
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/MapUnittestProto3.cs b/csharp/src/Google.Protobuf.Test.TestProtos/MapUnittestProto3.cs index 57e59a9..d3284a4 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/MapUnittestProto3.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/MapUnittestProto3.cs
@@ -580,23 +580,23 @@ if (other == null) { return; } - mapInt32Int32_.Add(other.mapInt32Int32_); - mapInt64Int64_.Add(other.mapInt64Int64_); - mapUint32Uint32_.Add(other.mapUint32Uint32_); - mapUint64Uint64_.Add(other.mapUint64Uint64_); - mapSint32Sint32_.Add(other.mapSint32Sint32_); - mapSint64Sint64_.Add(other.mapSint64Sint64_); - mapFixed32Fixed32_.Add(other.mapFixed32Fixed32_); - mapFixed64Fixed64_.Add(other.mapFixed64Fixed64_); - mapSfixed32Sfixed32_.Add(other.mapSfixed32Sfixed32_); - mapSfixed64Sfixed64_.Add(other.mapSfixed64Sfixed64_); - mapInt32Float_.Add(other.mapInt32Float_); - mapInt32Double_.Add(other.mapInt32Double_); - mapBoolBool_.Add(other.mapBoolBool_); - mapStringString_.Add(other.mapStringString_); - mapInt32Bytes_.Add(other.mapInt32Bytes_); - mapInt32Enum_.Add(other.mapInt32Enum_); - mapInt32ForeignMessage_.Add(other.mapInt32ForeignMessage_); + mapInt32Int32_.MergeFrom(other.mapInt32Int32_); + mapInt64Int64_.MergeFrom(other.mapInt64Int64_); + mapUint32Uint32_.MergeFrom(other.mapUint32Uint32_); + mapUint64Uint64_.MergeFrom(other.mapUint64Uint64_); + mapSint32Sint32_.MergeFrom(other.mapSint32Sint32_); + mapSint64Sint64_.MergeFrom(other.mapSint64Sint64_); + mapFixed32Fixed32_.MergeFrom(other.mapFixed32Fixed32_); + mapFixed64Fixed64_.MergeFrom(other.mapFixed64Fixed64_); + mapSfixed32Sfixed32_.MergeFrom(other.mapSfixed32Sfixed32_); + mapSfixed64Sfixed64_.MergeFrom(other.mapSfixed64Sfixed64_); + mapInt32Float_.MergeFrom(other.mapInt32Float_); + mapInt32Double_.MergeFrom(other.mapInt32Double_); + mapBoolBool_.MergeFrom(other.mapBoolBool_); + mapStringString_.MergeFrom(other.mapStringString_); + mapInt32Bytes_.MergeFrom(other.mapInt32Bytes_); + mapInt32Enum_.MergeFrom(other.mapInt32Enum_); + mapInt32ForeignMessage_.MergeFrom(other.mapInt32ForeignMessage_); _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } @@ -1100,7 +1100,7 @@ if (other == null) { return; } - mapInt32Message_.Add(other.mapInt32Message_); + mapInt32Message_.MergeFrom(other.mapInt32Message_); _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } @@ -1298,8 +1298,8 @@ if (other == null) { return; } - map1_.Add(other.map1_); - map2_.Add(other.map2_); + map1_.MergeFrom(other.map1_); + map2_.MergeFrom(other.map2_); _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } @@ -1723,21 +1723,21 @@ if (other == null) { return; } - mapInt32Int32_.Add(other.mapInt32Int32_); - mapInt64Int64_.Add(other.mapInt64Int64_); - mapUint32Uint32_.Add(other.mapUint32Uint32_); - mapUint64Uint64_.Add(other.mapUint64Uint64_); - mapSint32Sint32_.Add(other.mapSint32Sint32_); - mapSint64Sint64_.Add(other.mapSint64Sint64_); - mapFixed32Fixed32_.Add(other.mapFixed32Fixed32_); - mapFixed64Fixed64_.Add(other.mapFixed64Fixed64_); - mapSfixed32Sfixed32_.Add(other.mapSfixed32Sfixed32_); - mapSfixed64Sfixed64_.Add(other.mapSfixed64Sfixed64_); - mapInt32Float_.Add(other.mapInt32Float_); - mapInt32Double_.Add(other.mapInt32Double_); - mapBoolBool_.Add(other.mapBoolBool_); - mapInt32Enum_.Add(other.mapInt32Enum_); - mapInt32ForeignMessage_.Add(other.mapInt32ForeignMessage_); + mapInt32Int32_.MergeFrom(other.mapInt32Int32_); + mapInt64Int64_.MergeFrom(other.mapInt64Int64_); + mapUint32Uint32_.MergeFrom(other.mapUint32Uint32_); + mapUint64Uint64_.MergeFrom(other.mapUint64Uint64_); + mapSint32Sint32_.MergeFrom(other.mapSint32Sint32_); + mapSint64Sint64_.MergeFrom(other.mapSint64Sint64_); + mapFixed32Fixed32_.MergeFrom(other.mapFixed32Fixed32_); + mapFixed64Fixed64_.MergeFrom(other.mapFixed64Fixed64_); + mapSfixed32Sfixed32_.MergeFrom(other.mapSfixed32Sfixed32_); + mapSfixed64Sfixed64_.MergeFrom(other.mapSfixed64Sfixed64_); + mapInt32Float_.MergeFrom(other.mapInt32Float_); + mapInt32Double_.MergeFrom(other.mapInt32Double_); + mapBoolBool_.MergeFrom(other.mapBoolBool_); + mapInt32Enum_.MergeFrom(other.mapInt32Enum_); + mapInt32ForeignMessage_.MergeFrom(other.mapInt32ForeignMessage_); _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } @@ -2031,7 +2031,7 @@ if (other == null) { return; } - type_.Add(other.type_); + type_.MergeFrom(other.type_); _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } @@ -2224,7 +2224,7 @@ if (other == null) { return; } - entry_.Add(other.entry_); + entry_.MergeFrom(other.entry_); _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); }
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto2.cs b/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto2.cs index 08b1aaf..d573455 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto2.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto2.cs
@@ -4344,25 +4344,25 @@ unpackedDouble_.Add(other.unpackedDouble_); unpackedBool_.Add(other.unpackedBool_); unpackedNestedEnum_.Add(other.unpackedNestedEnum_); - mapInt32Int32_.Add(other.mapInt32Int32_); - mapInt64Int64_.Add(other.mapInt64Int64_); - mapUint32Uint32_.Add(other.mapUint32Uint32_); - mapUint64Uint64_.Add(other.mapUint64Uint64_); - mapSint32Sint32_.Add(other.mapSint32Sint32_); - mapSint64Sint64_.Add(other.mapSint64Sint64_); - mapFixed32Fixed32_.Add(other.mapFixed32Fixed32_); - mapFixed64Fixed64_.Add(other.mapFixed64Fixed64_); - mapSfixed32Sfixed32_.Add(other.mapSfixed32Sfixed32_); - mapSfixed64Sfixed64_.Add(other.mapSfixed64Sfixed64_); - mapInt32Float_.Add(other.mapInt32Float_); - mapInt32Double_.Add(other.mapInt32Double_); - mapBoolBool_.Add(other.mapBoolBool_); - mapStringString_.Add(other.mapStringString_); - mapStringBytes_.Add(other.mapStringBytes_); - mapStringNestedMessage_.Add(other.mapStringNestedMessage_); - mapStringForeignMessage_.Add(other.mapStringForeignMessage_); - mapStringNestedEnum_.Add(other.mapStringNestedEnum_); - mapStringForeignEnum_.Add(other.mapStringForeignEnum_); + mapInt32Int32_.MergeFrom(other.mapInt32Int32_); + mapInt64Int64_.MergeFrom(other.mapInt64Int64_); + mapUint32Uint32_.MergeFrom(other.mapUint32Uint32_); + mapUint64Uint64_.MergeFrom(other.mapUint64Uint64_); + mapSint32Sint32_.MergeFrom(other.mapSint32Sint32_); + mapSint64Sint64_.MergeFrom(other.mapSint64Sint64_); + mapFixed32Fixed32_.MergeFrom(other.mapFixed32Fixed32_); + mapFixed64Fixed64_.MergeFrom(other.mapFixed64Fixed64_); + mapSfixed32Sfixed32_.MergeFrom(other.mapSfixed32Sfixed32_); + mapSfixed64Sfixed64_.MergeFrom(other.mapSfixed64Sfixed64_); + mapInt32Float_.MergeFrom(other.mapInt32Float_); + mapInt32Double_.MergeFrom(other.mapInt32Double_); + mapBoolBool_.MergeFrom(other.mapBoolBool_); + mapStringString_.MergeFrom(other.mapStringString_); + mapStringBytes_.MergeFrom(other.mapStringBytes_); + mapStringNestedMessage_.MergeFrom(other.mapStringNestedMessage_); + mapStringForeignMessage_.MergeFrom(other.mapStringForeignMessage_); + mapStringNestedEnum_.MergeFrom(other.mapStringNestedEnum_); + mapStringForeignEnum_.MergeFrom(other.mapStringForeignEnum_); if (other.HasData) { if (!HasData) { Data = new global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.Data();
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3.cs b/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3.cs index 520216f..74e2a57 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3.cs
@@ -3753,25 +3753,25 @@ unpackedDouble_.Add(other.unpackedDouble_); unpackedBool_.Add(other.unpackedBool_); unpackedNestedEnum_.Add(other.unpackedNestedEnum_); - mapInt32Int32_.Add(other.mapInt32Int32_); - mapInt64Int64_.Add(other.mapInt64Int64_); - mapUint32Uint32_.Add(other.mapUint32Uint32_); - mapUint64Uint64_.Add(other.mapUint64Uint64_); - mapSint32Sint32_.Add(other.mapSint32Sint32_); - mapSint64Sint64_.Add(other.mapSint64Sint64_); - mapFixed32Fixed32_.Add(other.mapFixed32Fixed32_); - mapFixed64Fixed64_.Add(other.mapFixed64Fixed64_); - mapSfixed32Sfixed32_.Add(other.mapSfixed32Sfixed32_); - mapSfixed64Sfixed64_.Add(other.mapSfixed64Sfixed64_); - mapInt32Float_.Add(other.mapInt32Float_); - mapInt32Double_.Add(other.mapInt32Double_); - mapBoolBool_.Add(other.mapBoolBool_); - mapStringString_.Add(other.mapStringString_); - mapStringBytes_.Add(other.mapStringBytes_); - mapStringNestedMessage_.Add(other.mapStringNestedMessage_); - mapStringForeignMessage_.Add(other.mapStringForeignMessage_); - mapStringNestedEnum_.Add(other.mapStringNestedEnum_); - mapStringForeignEnum_.Add(other.mapStringForeignEnum_); + mapInt32Int32_.MergeFrom(other.mapInt32Int32_); + mapInt64Int64_.MergeFrom(other.mapInt64Int64_); + mapUint32Uint32_.MergeFrom(other.mapUint32Uint32_); + mapUint64Uint64_.MergeFrom(other.mapUint64Uint64_); + mapSint32Sint32_.MergeFrom(other.mapSint32Sint32_); + mapSint64Sint64_.MergeFrom(other.mapSint64Sint64_); + mapFixed32Fixed32_.MergeFrom(other.mapFixed32Fixed32_); + mapFixed64Fixed64_.MergeFrom(other.mapFixed64Fixed64_); + mapSfixed32Sfixed32_.MergeFrom(other.mapSfixed32Sfixed32_); + mapSfixed64Sfixed64_.MergeFrom(other.mapSfixed64Sfixed64_); + mapInt32Float_.MergeFrom(other.mapInt32Float_); + mapInt32Double_.MergeFrom(other.mapInt32Double_); + mapBoolBool_.MergeFrom(other.mapBoolBool_); + mapStringString_.MergeFrom(other.mapStringString_); + mapStringBytes_.MergeFrom(other.mapStringBytes_); + mapStringNestedMessage_.MergeFrom(other.mapStringNestedMessage_); + mapStringForeignMessage_.MergeFrom(other.mapStringForeignMessage_); + mapStringNestedEnum_.MergeFrom(other.mapStringNestedEnum_); + mapStringForeignEnum_.MergeFrom(other.mapStringForeignEnum_); if (other.optionalBoolWrapper_ != null) { if (optionalBoolWrapper_ == null || other.OptionalBoolWrapper != false) { OptionalBoolWrapper = other.OptionalBoolWrapper;
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/Unittest.cs b/csharp/src/Google.Protobuf.Test.TestProtos/Unittest.cs index c1f43ce..7f1aca1 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/Unittest.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/Unittest.cs
@@ -24112,7 +24112,7 @@ if (other == null) { return; } - foo_.Add(other.foo_); + foo_.MergeFrom(other.foo_); _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } @@ -30708,7 +30708,7 @@ } OptionalGroup.MergeFrom(other.OptionalGroup); } - stringStringMap_.Add(other.stringStringMap_); + stringStringMap_.MergeFrom(other.stringStringMap_); switch (other.OneofFieldCase) { case OneofFieldOneofCase.OneofUint32: OneofUint32 = other.OneofUint32;
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestWellKnownTypes.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestWellKnownTypes.cs index 3ec8d35..50b9046 100644 --- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestWellKnownTypes.cs +++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestWellKnownTypes.cs
@@ -3258,24 +3258,24 @@ if (other == null) { return; } - anyField_.Add(other.anyField_); - apiField_.Add(other.apiField_); - durationField_.Add(other.durationField_); - emptyField_.Add(other.emptyField_); - fieldMaskField_.Add(other.fieldMaskField_); - sourceContextField_.Add(other.sourceContextField_); - structField_.Add(other.structField_); - timestampField_.Add(other.timestampField_); - typeField_.Add(other.typeField_); - doubleField_.Add(other.doubleField_); - floatField_.Add(other.floatField_); - int64Field_.Add(other.int64Field_); - uint64Field_.Add(other.uint64Field_); - int32Field_.Add(other.int32Field_); - uint32Field_.Add(other.uint32Field_); - boolField_.Add(other.boolField_); - stringField_.Add(other.stringField_); - bytesField_.Add(other.bytesField_); + anyField_.MergeFrom(other.anyField_); + apiField_.MergeFrom(other.apiField_); + durationField_.MergeFrom(other.durationField_); + emptyField_.MergeFrom(other.emptyField_); + fieldMaskField_.MergeFrom(other.fieldMaskField_); + sourceContextField_.MergeFrom(other.sourceContextField_); + structField_.MergeFrom(other.structField_); + timestampField_.MergeFrom(other.timestampField_); + typeField_.MergeFrom(other.typeField_); + doubleField_.MergeFrom(other.doubleField_); + floatField_.MergeFrom(other.floatField_); + int64Field_.MergeFrom(other.int64Field_); + uint64Field_.MergeFrom(other.uint64Field_); + int32Field_.MergeFrom(other.int32Field_); + uint32Field_.MergeFrom(other.uint32Field_); + boolField_.MergeFrom(other.boolField_); + stringField_.MergeFrom(other.stringField_); + bytesField_.MergeFrom(other.bytesField_); _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); }
diff --git a/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs b/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs index 8387291..17c5249 100644 --- a/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs +++ b/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs
@@ -36,6 +36,7 @@ using NUnit.Framework; using System.Linq; using Google.Protobuf.WellKnownTypes; +using Google.Protobuf.Collections; namespace Google.Protobuf { @@ -795,5 +796,44 @@ EqualityTester.AssertInequality(message1, message2); EqualityTester.AssertEquality(message1, message3); } + + [Test] + [TestCase(false)] + [TestCase(true)] + public void MapFieldMerging(bool direct) + { + var message1 = new TestMap + { + MapStringString = + { + { "x1", "y1" }, + { "common", "message1" } + } + }; + var message2 = new TestMap + { + MapStringString = + { + { "x2", "y2" }, + { "common", "message2" } + } + }; + if (direct) + { + message1.MergeFrom(message2); + } + else + { + message1.MergeFrom(message2.ToByteArray()); + } + + var expected = new MapField<string, string> + { + { "x1", "y1" }, + { "x2", "y2" }, + { "common", "message2" } + }; + Assert.AreEqual(expected, message1.MapStringString); + } } } \ No newline at end of file
diff --git a/csharp/src/Google.Protobuf/Collections/MapField.cs b/csharp/src/Google.Protobuf/Collections/MapField.cs index f0124ee..09afb75 100644 --- a/csharp/src/Google.Protobuf/Collections/MapField.cs +++ b/csharp/src/Google.Protobuf/Collections/MapField.cs
@@ -238,6 +238,21 @@ } /// <summary> + /// Adds the specified entries to the map, replacing any existing entries with the same keys. + /// The keys and values are not automatically cloned. + /// </summary> + /// <remarks>This method primarily exists to be called from MergeFrom methods in generated classes for messages.</remarks> + /// <param name="entries">The entries to add to the map.</param> + public void MergeFrom(IDictionary<TKey, TValue> entries) + { + ProtoPreconditions.CheckNotNull(entries, nameof(entries)); + foreach (var pair in entries) + { + this[pair.Key] = pair.Value; + } + } + + /// <summary> /// Returns an enumerator that iterates through the collection. /// </summary> /// <returns>
diff --git a/csharp/src/Google.Protobuf/MessageParser.cs b/csharp/src/Google.Protobuf/MessageParser.cs index 66907d4..5710292 100644 --- a/csharp/src/Google.Protobuf/MessageParser.cs +++ b/csharp/src/Google.Protobuf/MessageParser.cs
@@ -171,6 +171,10 @@ /// <summary> /// Parses a message from the given JSON. /// </summary> + /// <remarks>This method always uses the default JSON parser; it is not affected by <see cref="WithDiscardUnknownFields(bool)"/>. + /// To ignore unknown fields when parsing JSON, create a <see cref="JsonParser"/> using a <see cref="JsonParser.Settings"/> + /// with <see cref="JsonParser.Settings.IgnoreUnknownFields"/> set to true and call <see cref="JsonParser.Parse{T}(string)"/> directly. + /// </remarks> /// <param name="json">The JSON to parse.</param> /// <returns>The parsed message.</returns> /// <exception cref="InvalidJsonException">The JSON does not comply with RFC 7159</exception> @@ -203,6 +207,9 @@ /// <summary> /// Creates a new message parser which optionally discards unknown fields when parsing. /// </summary> + /// <remarks>Note that this does not affect the behavior of <see cref="ParseJson(string)"/> + /// at all. To ignore unknown fields when parsing JSON, create a <see cref="JsonParser"/> using a <see cref="JsonParser.Settings"/> + /// with <see cref="JsonParser.Settings.IgnoreUnknownFields"/> set to true and call <see cref="JsonParser.Parse{T}(string)"/> directly.</remarks> /// <param name="discardUnknownFields">Whether or not to discard unknown fields when parsing.</param> /// <returns>A newly configured message parser.</returns> public MessageParser WithDiscardUnknownFields(bool discardUnknownFields) =>
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs index 8c1eec5..aa25686 100644 --- a/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs +++ b/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs
@@ -212,7 +212,7 @@ if (other == null) { return; } - fields_.Add(other.fields_); + fields_.MergeFrom(other.fields_); _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); }
diff --git a/kokoro/linux/cmake/build.sh b/kokoro/linux/cmake/build.sh index 1b0ebfc..523253d 100755 --- a/kokoro/linux/cmake/build.sh +++ b/kokoro/linux/cmake/build.sh
@@ -1,6 +1,6 @@ #!/bin/bash # -# Build file to set up and run tests based on distribution archive +# Build file to set up and run tests using CMake set -eux
diff --git a/kokoro/linux/cmake_install/build.sh b/kokoro/linux/cmake_install/build.sh index 6fdafa5..7fdf267 100755 --- a/kokoro/linux/cmake_install/build.sh +++ b/kokoro/linux/cmake_install/build.sh
@@ -1,6 +1,6 @@ #!/bin/bash # -# Build file to set up and run tests based on distribution archive +# Build file to build, install, and test using CMake. set -eux
diff --git a/kokoro/linux/cmake_ninja/build.sh b/kokoro/linux/cmake_ninja/build.sh index d3a281f..21cc01e 100755 --- a/kokoro/linux/cmake_ninja/build.sh +++ b/kokoro/linux/cmake_ninja/build.sh
@@ -1,6 +1,6 @@ #!/bin/bash # -# Build file to set up and run tests based on distribution archive +# Build file to set up and run tests using CMake with the Ninja generator. set -eux
diff --git a/kokoro/linux/cmake_shared/build.sh b/kokoro/linux/cmake_shared/build.sh new file mode 100755 index 0000000..87dde41 --- /dev/null +++ b/kokoro/linux/cmake_shared/build.sh
@@ -0,0 +1,7 @@ +#!/bin/bash +# +# Build file to set up and run tests via CMake using shared libraries + +set -eux + +# TODO(mkruskal) Implement this. \ No newline at end of file
diff --git a/kokoro/linux/cmake_shared/continuous.cfg b/kokoro/linux/cmake_shared/continuous.cfg new file mode 100644 index 0000000..f03bd39 --- /dev/null +++ b/kokoro/linux/cmake_shared/continuous.cfg
@@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/cmake/build.sh" +timeout_mins: 1440 + +action { + define_artifacts { + regex: "**/sponge_log.*" + } +}
diff --git a/kokoro/linux/cmake_shared/presubmit.cfg b/kokoro/linux/cmake_shared/presubmit.cfg new file mode 100644 index 0000000..f03bd39 --- /dev/null +++ b/kokoro/linux/cmake_shared/presubmit.cfg
@@ -0,0 +1,11 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/linux/cmake/build.sh" +timeout_mins: 1440 + +action { + define_artifacts { + regex: "**/sponge_log.*" + } +}
diff --git a/kokoro/windows/bazel/build.bat b/kokoro/windows/bazel/build.bat new file mode 100644 index 0000000..52b83f4 --- /dev/null +++ b/kokoro/windows/bazel/build.bat
@@ -0,0 +1,4 @@ +@rem enter repo root +cd /d %~dp0\..\..\.. + +@rem TODO(mkruskal) Implement tests
diff --git a/kokoro/windows/bazel/continuous.cfg b/kokoro/windows/bazel/continuous.cfg new file mode 100644 index 0000000..37e89e0 --- /dev/null +++ b/kokoro/windows/bazel/continuous.cfg
@@ -0,0 +1,5 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/windows/cmake/build.bat" +timeout_mins: 1440
diff --git a/kokoro/windows/bazel/presubmit.cfg b/kokoro/windows/bazel/presubmit.cfg new file mode 100644 index 0000000..37e89e0 --- /dev/null +++ b/kokoro/windows/bazel/presubmit.cfg
@@ -0,0 +1,5 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/windows/cmake/build.bat" +timeout_mins: 1440
diff --git a/kokoro/windows/cmake_shared/build.bat b/kokoro/windows/cmake_shared/build.bat new file mode 100644 index 0000000..52b83f4 --- /dev/null +++ b/kokoro/windows/cmake_shared/build.bat
@@ -0,0 +1,4 @@ +@rem enter repo root +cd /d %~dp0\..\..\.. + +@rem TODO(mkruskal) Implement tests
diff --git a/kokoro/windows/cmake_shared/continuous.cfg b/kokoro/windows/cmake_shared/continuous.cfg new file mode 100644 index 0000000..37e89e0 --- /dev/null +++ b/kokoro/windows/cmake_shared/continuous.cfg
@@ -0,0 +1,5 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/windows/cmake/build.bat" +timeout_mins: 1440
diff --git a/kokoro/windows/cmake_shared/presubmit.cfg b/kokoro/windows/cmake_shared/presubmit.cfg new file mode 100644 index 0000000..37e89e0 --- /dev/null +++ b/kokoro/windows/cmake_shared/presubmit.cfg
@@ -0,0 +1,5 @@ +# Config file for running tests in Kokoro + +# Location of the build script in repository +build_file: "protobuf/kokoro/windows/cmake/build.bat" +timeout_mins: 1440
diff --git a/python/google/protobuf/message.py b/python/google/protobuf/message.py index 76c6802..0fe6a4f 100644 --- a/python/google/protobuf/message.py +++ b/python/google/protobuf/message.py
@@ -74,7 +74,8 @@ __slots__ = [] - #: The :class:`google.protobuf.descriptor.Descriptor` for this message type. + #: The :class:`google.protobuf.Descriptor` + # for this message type. DESCRIPTOR = None def __deepcopy__(self, memo=None):
diff --git a/src/google/protobuf/arenaz_sampler.cc b/src/google/protobuf/arenaz_sampler.cc index ab524fb..53b524e 100644 --- a/src/google/protobuf/arenaz_sampler.cc +++ b/src/google/protobuf/arenaz_sampler.cc
@@ -56,13 +56,20 @@ PROTOBUF_CONSTINIT std::atomic<bool> g_arenaz_enabled{true}; PROTOBUF_CONSTINIT std::atomic<int32_t> g_arenaz_sample_parameter{1 << 10}; +PROTOBUF_CONSTINIT std::atomic<ThreadSafeArenazConfigListener> + g_arenaz_config_listener{nullptr}; PROTOBUF_THREAD_LOCAL absl::profiling_internal::ExponentialBiased g_exponential_biased_generator; +void TriggerThreadSafeArenazConfigListener() { + auto* listener = g_arenaz_config_listener.load(std::memory_order_acquire); + if (listener != nullptr) listener(); +} + } // namespace PROTOBUF_THREAD_LOCAL SamplingState global_sampling_state = { - .next_sample = int64_t{1} << 10, .sample_stride = int64_t{1} << 10}; + /*next_sample=*/0, /*sample_stride=*/0}; ThreadSafeArenaStats::ThreadSafeArenaStats() { PrepareForSampling(0); } ThreadSafeArenaStats::~ThreadSafeArenaStats() = default; @@ -118,11 +125,29 @@ return GlobalThreadSafeArenazSampler().Register(old_stride); } +void SetThreadSafeArenazConfigListener(ThreadSafeArenazConfigListener l) { + g_arenaz_config_listener.store(l, std::memory_order_release); +} + +bool IsThreadSafeArenazEnabled() { + return g_arenaz_enabled.load(std::memory_order_acquire); +} + void SetThreadSafeArenazEnabled(bool enabled) { + SetThreadSafeArenazEnabledInternal(enabled); + TriggerThreadSafeArenazConfigListener(); +} + +void SetThreadSafeArenazEnabledInternal(bool enabled) { g_arenaz_enabled.store(enabled, std::memory_order_release); } void SetThreadSafeArenazSampleParameter(int32_t rate) { + SetThreadSafeArenazSampleParameterInternal(rate); + TriggerThreadSafeArenazConfigListener(); +} + +void SetThreadSafeArenazSampleParameterInternal(int32_t rate) { if (rate > 0) { g_arenaz_sample_parameter.store(rate, std::memory_order_release); } else { @@ -136,6 +161,11 @@ } void SetThreadSafeArenazMaxSamples(int32_t max) { + SetThreadSafeArenazMaxSamplesInternal(max); + TriggerThreadSafeArenazConfigListener(); +} + +void SetThreadSafeArenazMaxSamplesInternal(int32_t max) { if (max > 0) { GlobalThreadSafeArenazSampler().SetMaxSamples(max); } else { @@ -144,6 +174,10 @@ } } +size_t ThreadSafeArenazMaxSamples() { + return GlobalThreadSafeArenazSampler().GetMaxSamples(); +} + void SetThreadSafeArenazGlobalNextSample(int64_t next_sample) { if (next_sample >= 0) { global_sampling_state.next_sample = next_sample; @@ -160,10 +194,16 @@ return nullptr; } +void SetThreadSafeArenazConfigListener(ThreadSafeArenazConfigListener) {} void SetThreadSafeArenazEnabled(bool enabled) {} +void SetThreadSafeArenazEnabledInternal(bool enabled) {} +bool IsThreadSafeArenazEnabled() { return false; } void SetThreadSafeArenazSampleParameter(int32_t rate) {} +void SetThreadSafeArenazSampleParameterInternal(int32_t rate) {} int32_t ThreadSafeArenazSampleParameter() { return 0; } void SetThreadSafeArenazMaxSamples(int32_t max) {} +void SetThreadSafeArenazMaxSamplesInternal(int32_t max) {} +size_t ThreadSafeArenazMaxSamples() { return 0; } void SetThreadSafeArenazGlobalNextSample(int64_t next_sample) {} #endif // defined(PROTOBUF_ARENAZ_SAMPLE)
diff --git a/src/google/protobuf/arenaz_sampler.h b/src/google/protobuf/arenaz_sampler.h index e9a4dec..43d1acb 100644 --- a/src/google/protobuf/arenaz_sampler.h +++ b/src/google/protobuf/arenaz_sampler.h
@@ -199,17 +199,29 @@ // Returns a global Sampler. ThreadSafeArenazSampler& GlobalThreadSafeArenazSampler(); +using ThreadSafeArenazConfigListener = void (*)(); +void SetThreadSafeArenazConfigListener(ThreadSafeArenazConfigListener l); + // Enables or disables sampling for thread safe arenas. void SetThreadSafeArenazEnabled(bool enabled); +void SetThreadSafeArenazEnabledInternal(bool enabled); + +// Returns true if sampling is on, false otherwise. +bool IsThreadSafeArenazEnabled(); // Sets the rate at which thread safe arena will be sampled. void SetThreadSafeArenazSampleParameter(int32_t rate); +void SetThreadSafeArenazSampleParameterInternal(int32_t rate); // Returns the rate at which thread safe arena will be sampled. int32_t ThreadSafeArenazSampleParameter(); // Sets a soft max for the number of samples that will be kept. void SetThreadSafeArenazMaxSamples(int32_t max); +void SetThreadSafeArenazMaxSamplesInternal(int32_t max); + +// Returns the max number of samples that will be kept. +size_t ThreadSafeArenazMaxSamples(); // Sets the current value for when arenas should be next sampled. void SetThreadSafeArenazGlobalNextSample(int64_t next_sample);
diff --git a/src/google/protobuf/arenaz_sampler_test.cc b/src/google/protobuf/arenaz_sampler_test.cc index 1b73938..774e70d 100644 --- a/src/google/protobuf/arenaz_sampler_test.cc +++ b/src/google/protobuf/arenaz_sampler_test.cc
@@ -375,6 +375,7 @@ SetThreadSafeArenazEnabled(true); // Setting 1 as the parameter value means one in every two arenas would be // sampled, on average. + int32_t oldparam = ThreadSafeArenazSampleParameter(); SetThreadSafeArenazSampleParameter(1); SetThreadSafeArenazGlobalNextSample(0); auto& sampler = GlobalThreadSafeArenazSampler(); @@ -402,6 +403,95 @@ } } EXPECT_GT(count, 0); + SetThreadSafeArenazSampleParameter(oldparam); +} + +class SampleFirstArenaThread : public Thread { + protected: + void Run() override { + google::protobuf::Arena arena; + google::protobuf::ArenaSafeUniquePtr< + protobuf_test_messages::proto2::TestAllTypesProto2> + message = google::protobuf::MakeArenaSafeUnique< + protobuf_test_messages::proto2::TestAllTypesProto2>(&arena); + GOOGLE_CHECK(message != nullptr); + arena_created_.Notify(); + samples_counted_.WaitForNotification(); + } + + public: + explicit SampleFirstArenaThread(const thread::Options& options) + : Thread(options, "SampleFirstArenaThread") {} + + absl::Notification arena_created_; + absl::Notification samples_counted_; +}; + +// Test that the first arena created on a thread may and may not be chosen for +// sampling. +TEST(ThreadSafeArenazSamplerTest, SampleFirstArena) { + SetThreadSafeArenazEnabled(true); + auto& sampler = GlobalThreadSafeArenazSampler(); + + enum class SampleResult { + kSampled, + kUnsampled, + kSpoiled, + }; + + auto count_samples = [&]() { + int count = 0; + sampler.Iterate([&](const ThreadSafeArenaStats& h) { ++count; }); + return count; + }; + + auto run_sample_experiment = [&]() { + int before = count_samples(); + thread::Options options; + options.set_joinable(true); + SampleFirstArenaThread t(options); + t.Start(); + t.arena_created_.WaitForNotification(); + int during = count_samples(); + t.samples_counted_.Notify(); + t.Join(); + int after = count_samples(); + + // If we didn't get back where we were, some other thread may have + // created an arena and produced an invalid experiment run. + if (before != after) return SampleResult::kSpoiled; + + switch (during - before) { + case 1: + return SampleResult::kSampled; + case 0: + return SampleResult::kUnsampled; + default: + return SampleResult::kSpoiled; + } + }; + + constexpr int kTrials = 10000; + bool sampled = false; + bool unsampled = false; + for (int i = 0; i < kTrials; ++i) { + switch (run_sample_experiment()) { + case SampleResult::kSampled: + sampled = true; + break; + case SampleResult::kUnsampled: + unsampled = true; + break; + default: + break; + } + + // This is the success criteria for the entire test. At some point + // we sampled the first arena and at some point we did not. + if (sampled && unsampled) return; + } + EXPECT_TRUE(sampled); + EXPECT_TRUE(unsampled); } #endif // defined(PROTOBUF_ARENAZ_SAMPLE)
diff --git a/src/google/protobuf/compiler/cpp/message.cc b/src/google/protobuf/compiler/cpp/message.cc index 51a3e65..50b86f7 100644 --- a/src/google/protobuf/compiler/cpp/message.cc +++ b/src/google/protobuf/compiler/cpp/message.cc
@@ -2205,11 +2205,12 @@ " if (IsSplitMessageDefault()) {\n" " void* chunk = " "::PROTOBUF_NAMESPACE_ID::internal::CreateSplitMessageGeneric(" - "GetArenaForAllocation(), &$1$, sizeof(Impl_::Split));\n" + "GetArenaForAllocation(), &$1$, sizeof(Impl_::Split), this, &$2$);\n" " $split$ = reinterpret_cast<Impl_::Split*>(chunk);\n" " }\n" "}\n", - DefaultInstanceName(descriptor_, options_, /*split=*/true)); + DefaultInstanceName(descriptor_, options_, /*split=*/true), + DefaultInstanceName(descriptor_, options_, /*split=*/false)); } GenerateVerify(printer);
diff --git a/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc b/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc index e21eff1..56b920d 100644 --- a/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc +++ b/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc
@@ -74,6 +74,22 @@ EXPECT_FALSE(IsDescriptorOptionMessage(DescriptorProto::descriptor())); } +TEST(CSharpIdentifiers, UnderscoresToCamelCase) { + EXPECT_EQ("FooBar", UnderscoresToCamelCase("Foo_Bar", true)); + EXPECT_EQ("fooBar", UnderscoresToCamelCase("FooBar", false)); + EXPECT_EQ("foo123", UnderscoresToCamelCase("foo_123", false)); + // remove leading underscores + EXPECT_EQ("Foo123", UnderscoresToCamelCase("_Foo_123", true)); + // this one has slight unexpected output as it capitalises the first + // letter after consuming the underscores, but this was the existing + // behaviour so I have not changed it + EXPECT_EQ("FooBar", UnderscoresToCamelCase("___fooBar", false)); + // leave a leading underscore for identifiers that would otherwise + // be invalid because they would start with a digit + EXPECT_EQ("_123Foo", UnderscoresToCamelCase("_123_foo", true)); + EXPECT_EQ("_123Foo", UnderscoresToCamelCase("___123_foo", true)); +} + } // namespace } // namespace csharp } // namespace compiler
diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.cc b/src/google/protobuf/compiler/csharp/csharp_helpers.cc index aa84dc7..1b58b95 100644 --- a/src/google/protobuf/compiler/csharp/csharp_helpers.cc +++ b/src/google/protobuf/compiler/csharp/csharp_helpers.cc
@@ -144,6 +144,7 @@ bool cap_next_letter, bool preserve_period) { std::string result; + // Note: I distrust ctype.h due to locales. for (int i = 0; i < input.size(); i++) { if ('a' <= input[i] && input[i] <= 'z') { @@ -177,6 +178,23 @@ if (input.size() > 0 && input[input.size() - 1] == '#') { result += '_'; } + + // https://github.com/protocolbuffers/protobuf/issues/8101 + // To avoid generating invalid identifiers - if the input string + // starts with _<digit> (or multiple underscores then digit) then + // we need to preserve the underscore as an identifier cannot start + // with a digit. + // This check is being done after the loop rather than before + // to handle the case where there are multiple underscores before the + // first digit. We let them all be consumed so we can see if we would + // start with a digit. + // Note: not preserving leading underscores for all otherwise valid identifiers + // so as to not break anything that relies on the existing behaviour + if (result.size() > 0 && ('0' <= result[0] && result[0] <= '9') + && input.size() > 0 && input[0] == '_') + { + result.insert(0, 1, '_'); + } return result; }
diff --git a/src/google/protobuf/compiler/csharp/csharp_map_field.cc b/src/google/protobuf/compiler/csharp/csharp_map_field.cc index a13b995..9efd3d5 100644 --- a/src/google/protobuf/compiler/csharp/csharp_map_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_map_field.cc
@@ -90,7 +90,7 @@ void MapFieldGenerator::GenerateMergingCode(io::Printer* printer) { printer->Print( variables_, - "$name$_.Add(other.$name$_);\n"); + "$name$_.MergeFrom(other.$name$_);\n"); } void MapFieldGenerator::GenerateParsingCode(io::Printer* printer) {
diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc index 0353b74..70014b2 100644 --- a/src/google/protobuf/generated_message_reflection.cc +++ b/src/google/protobuf/generated_message_reflection.cc
@@ -2514,6 +2514,7 @@ } void Reflection::PrepareSplitMessageForWrite(Message* message) const { + GOOGLE_DCHECK_NE(message, schema_.default_instance_); void** split = MutableSplitField(message); const void* default_split = GetSplitField(schema_.default_instance_); if (*split == default_split) {
diff --git a/src/google/protobuf/io/tokenizer.cc b/src/google/protobuf/io/tokenizer.cc index f9e0776..9614d01 100644 --- a/src/google/protobuf/io/tokenizer.cc +++ b/src/google/protobuf/io/tokenizer.cc
@@ -406,7 +406,7 @@ case '\n': { if (!allow_multiline_strings_) { - AddError("String literals cannot cross line boundaries."); + AddError("Multiline strings are not allowed. Did you miss a \"?."); return; } NextChar();
diff --git a/src/google/protobuf/io/tokenizer_unittest.cc b/src/google/protobuf/io/tokenizer_unittest.cc index 16ba940..6233d6a 100644 --- a/src/google/protobuf/io/tokenizer_unittest.cc +++ b/src/google/protobuf/io/tokenizer_unittest.cc
@@ -1067,7 +1067,8 @@ {"'\\X' foo", true, "0:2: Invalid escape sequence in string literal.\n"}, {"'\\x' foo", true, "0:3: Expected hex digits for escape sequence.\n"}, {"'foo", false, "0:4: Unexpected end of string.\n"}, - {"'bar\nfoo", true, "0:4: String literals cannot cross line boundaries.\n"}, + {"'bar\nfoo", true, + "0:4: Multiline strings are not allowed. Did you miss a \"?.\n"}, {"'\\u01' foo", true, "0:5: Expected four hex digits for \\u escape sequence.\n"}, {"'\\u01' foo", true,
diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc index 1279164..5052b1c 100644 --- a/src/google/protobuf/message.cc +++ b/src/google/protobuf/message.cc
@@ -215,7 +215,9 @@ namespace internal { void* CreateSplitMessageGeneric(Arena* arena, const void* default_split, - size_t size) { + size_t size, const void* message, + const void* default_message) { + GOOGLE_DCHECK_NE(message, default_message); void* split = (arena == nullptr) ? ::operator new(size) : arena->AllocateAligned(size); memcpy(split, default_split, size);
diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h index b61fafb..5a9111f 100644 --- a/src/google/protobuf/message.h +++ b/src/google/protobuf/message.h
@@ -412,7 +412,8 @@ namespace internal { // Creates and returns an allocation for a split message. void* CreateSplitMessageGeneric(Arena* arena, const void* default_split, - size_t size); + size_t size, const void* message, + const void* default_message); // Forward-declare interfaces used to implement RepeatedFieldRef. // These are protobuf internals that users shouldn't care about.
diff --git a/src/google/protobuf/port_def.inc b/src/google/protobuf/port_def.inc index ea3d682..7d067fd 100644 --- a/src/google/protobuf/port_def.inc +++ b/src/google/protobuf/port_def.inc
@@ -699,7 +699,7 @@ // uses Clang 12.0.5. # elif !defined(__CYGWIN__) && \ __has_cpp_attribute(clang::require_constant_initialization) && \ - ((defined(__APPLE__) && PROTOBUF_CLANG_MIN(13, 0)) || \ + ((defined(__APPLE__) && PROTOBUF_CLANG_MIN(13, 0)) || \ (!defined(__APPLE__) && PROTOBUF_CLANG_MIN(12, 0))) # define PROTOBUF_CONSTINIT [[clang::require_constant_initialization]] # define PROTOBUF_CONSTEXPR constexpr
diff --git a/src/google/protobuf/unittest.proto b/src/google/protobuf/unittest.proto index 7176f09..de78f9a 100644 --- a/src/google/protobuf/unittest.proto +++ b/src/google/protobuf/unittest.proto
@@ -346,6 +346,16 @@ optional bytes oneof_bytes_extension = 114; } +message TestMixedFieldsAndExtensions { + optional int32 a = 1; + repeated fixed32 b = 3; + extensions 2, 4; + extend TestMixedFieldsAndExtensions { + optional int32 c = 2; + repeated fixed32 d = 4; + } +} + message TestGroup { optional group OptionalGroup = 16 { optional int32 a = 17;
diff --git a/src/google/protobuf/util/json_format_proto3.proto b/src/google/protobuf/util/json_format_proto3.proto index f9c5199..4df5eb9 100644 --- a/src/google/protobuf/util/json_format_proto3.proto +++ b/src/google/protobuf/util/json_format_proto3.proto
@@ -189,6 +189,14 @@ int32 value = 1 [json_name = "@value"]; } +message TestEvilJson { + int32 regular_value = 1 [json_name = "regular_name"]; + int32 script = 2 [json_name = "</script>"]; + int32 quotes = 3 [json_name = "unbalanced\"quotes"]; + int32 script_and_quotes = 4 + [json_name = "\"<script>alert('hello!);</script>"]; +} + message TestExtensions { .protobuf_unittest.TestAllExtensions extensions = 1; }
diff --git a/src/google/protobuf/util/json_util_test.cc b/src/google/protobuf/util/json_util_test.cc index be0d39e..99272d7 100644 --- a/src/google/protobuf/util/json_util_test.cc +++ b/src/google/protobuf/util/json_util_test.cc
@@ -64,6 +64,11 @@ // Must be included last. #include <google/protobuf/port_def.inc> +bool IsJson2() { + // Pay no attention to the person behind the curtain. + return false; +} + namespace google { namespace protobuf { namespace util { @@ -76,6 +81,7 @@ using ::proto3::TestWrapper; using ::proto_util_converter::testing::MapIn; using ::testing::ElementsAre; +using ::testing::Not; using ::testing::SizeIs; // TODO(b/234474291): Use the gtest versions once that's available in OSS. @@ -274,20 +280,37 @@ // The ESF parser actually gets this wrong, and serializes floats whose // default value is non-finite as 0. We make sure to reproduce this bug. - EXPECT_THAT( - ToJson(protobuf_unittest::TestExtremeDefaultValues(), options), - IsOkAndHolds( - R"({"escapedBytes":"XDAwMFwwMDFcMDA3XDAxMFwwMTRcblxyXHRcMDEzXFxcJ1wiXDM3Ng==")" - R"(,"largeUint32":4294967295,"largeUint64":"18446744073709551615",)" - R"("smallInt32":-2147483647,"smallInt64":"-9223372036854775807")" - R"(,"reallySmallInt32":-2147483648,"reallySmallInt64":"-9223372036854775808",)" - R"("utf8String":"ሴ","zeroFloat":0,"oneFloat":1,"smallFloat":1.5,)" - R"("negativeOneFloat":-1,"negativeFloat":-1.5,"largeFloat":2e+08,)" - R"("smallNegativeFloat":-8e-28,"infDouble":0,"negInfDouble":0)" - R"(,"nanDouble":0,"infFloat":0,"negInfFloat":0,"nanFloat":0)" - R"(,"cppTrigraph":"? ? ?? ?? ??? ??/ ??-","stringWithZero":"hel\u0000lo")" - R"(,"bytesWithZero":"d29yXDAwMGxk","stringPieceWithZero":"ab\u0000c")" - R"(,"cordWithZero":"12\u00003","replacementString":"${unknown}"})")); + if (IsJson2()) { + EXPECT_THAT( + ToJson(protobuf_unittest::TestExtremeDefaultValues(), options), + IsOkAndHolds( + R"({"escapedBytes":"XDAwMFwwMDFcMDA3XDAxMFwwMTRcblxyXHRcMDEzXFxcJ1wiXDM3Ng==")" + R"(,"largeUint32":4294967295,"largeUint64":"18446744073709551615",)" + R"("smallInt32":-2147483647,"smallInt64":"-9223372036854775807",)" + R"("utf8String":"ሴ","zeroFloat":0,"oneFloat":1,"smallFloat":1.5,)" + R"("negativeOneFloat":-1,"negativeFloat":-1.5,"largeFloat":2e+08,)" + R"("smallNegativeFloat":-8e-28,"infDouble":0,"negInfDouble":0,)" + R"("nanDouble":0,"infFloat":0,"negInfFloat":0,"nanFloat":0,)" + R"("cppTrigraph":"? ? ?? ?? ??? ??/ ??-","reallySmallInt32":-2147483648)" + R"(,"reallySmallInt64":"-9223372036854775808","stringWithZero":"hel\u0000lo")" + R"(,"bytesWithZero":"d29yXDAwMGxk","stringPieceWithZero":"ab\u0000c")" + R"(,"cordWithZero":"12\u00003","replacementString":"${unknown}"})")); + } else { + EXPECT_THAT( + ToJson(protobuf_unittest::TestExtremeDefaultValues(), options), + IsOkAndHolds( + R"({"escapedBytes":"XDAwMFwwMDFcMDA3XDAxMFwwMTRcblxyXHRcMDEzXFxcJ1wiXDM3Ng==")" + R"(,"largeUint32":4294967295,"largeUint64":"18446744073709551615",)" + R"("smallInt32":-2147483647,"smallInt64":"-9223372036854775807")" + R"(,"reallySmallInt32":-2147483648,"reallySmallInt64":"-9223372036854775808",)" + R"("utf8String":"ሴ","zeroFloat":0,"oneFloat":1,"smallFloat":1.5,)" + R"("negativeOneFloat":-1,"negativeFloat":-1.5,"largeFloat":2e+08,)" + R"("smallNegativeFloat":-8e-28,"infDouble":0,"negInfDouble":0)" + R"(,"nanDouble":0,"infFloat":0,"negInfFloat":0,"nanFloat":0)" + R"(,"cppTrigraph":"? ? ?? ?? ??? ??/ ??-","stringWithZero":"hel\u0000lo")" + R"(,"bytesWithZero":"d29yXDAwMGxk","stringPieceWithZero":"ab\u0000c")" + R"(,"cordWithZero":"12\u00003","replacementString":"${unknown}"})")); + } } TEST_P(JsonTest, TestPreserveProtoFieldNames) { @@ -762,6 +785,20 @@ } )json"), StatusIs(util::StatusCode::kInvalidArgument)); + + TestAny m2; + m2.mutable_value(); + EXPECT_THAT(ToJson(m2), IsOkAndHolds(R"({"value":{}})")); + m2.mutable_value()->set_value("garbage"); + // The ESF parser does not return InvalidArgument for this error. + EXPECT_THAT(ToJson(m2), Not(StatusIs(util::StatusCode::kOk))); + + m2.Clear(); + m2.mutable_value()->set_type_url("type.googleapis.com/proto3.TestMessage"); + EXPECT_THAT( + ToJson(m2), + IsOkAndHolds( + R"({"value":{"@type":"type.googleapis.com/proto3.TestMessage"}})")); } TEST_P(JsonTest, TestFlatList) { @@ -952,6 +989,37 @@ EXPECT_EQ(m.enum_value(), proto3::BAR); } +// This functionality is not correctly implemented by the ESF parser, so +// the test is only turned on when testing json2. +TEST_P(JsonTest, Extensions) { + if (GetParam() == Codec::kResolver || !IsJson2()) { + GTEST_SKIP(); + } + + auto m = ToProto<protobuf_unittest::TestMixedFieldsAndExtensions>(R"json({ + "[protobuf_unittest.TestMixedFieldsAndExtensions.c]": 42, + "a": 5, + "b": [1, 2, 3], + "[protobuf_unittest.TestMixedFieldsAndExtensions.d]": [1, 1, 2, 3, 5, 8, 13] + })json"); + ASSERT_OK(m); + EXPECT_EQ(m->a(), 5); + EXPECT_THAT(m->b(), ElementsAre(1, 2, 3)); + EXPECT_EQ(m->GetExtension(protobuf_unittest::TestMixedFieldsAndExtensions::c), + 42); + EXPECT_THAT( + m->GetRepeatedExtension(protobuf_unittest::TestMixedFieldsAndExtensions::d), + ElementsAre(1, 1, 2, 3, 5, 8, 13)); + + EXPECT_THAT( + ToJson(*m), + IsOkAndHolds( + R"({"a":5,)" + R"("[protobuf_unittest.TestMixedFieldsAndExtensions.c]":42,)" + R"("b":[1,2,3],)" + R"("[protobuf_unittest.TestMixedFieldsAndExtensions.d]":[1,1,2,3,5,8,13]})")); +} + // Parsing does NOT work like MergeFrom: existing repeated field values are // clobbered, not appended to. TEST_P(JsonTest, TestOverwriteRepeated) { @@ -1158,6 +1226,34 @@ m.set_string_value("</script>"); EXPECT_THAT(ToJson(m), IsOkAndHolds(R"({"stringValue":"\u003c/script\u003e"})")); + + proto3::TestEvilJson m2; + JsonPrintOptions opts; + opts.always_print_primitive_fields = true; + EXPECT_THAT( + ToJson(m2, opts), + IsOkAndHolds( + R"({"regular_name":0,"\u003c/script\u003e":0,)" + R"("unbalanced\"quotes":0,)" + R"("\"\u003cscript\u003ealert('hello!);\u003c/script\u003e":0})")); +} + +TEST_P(JsonTest, FieldOrder) { + // $ protoscope -s <<< "3: 3 22: 2 1: 1 22: 2" + std::string out; + util::Status s = BinaryToJsonString( + resolver_.get(), "type.googleapis.com/proto3.TestMessage", + "\x18\x03\xb0\x01\x02\x08\x01\xb0\x01\x02", &out); + ASSERT_OK(s); + if (IsJson2()) { + EXPECT_EQ( + out, + R"({"boolValue":true,"int64Value":"3","repeatedInt32Value":[2,2]})"); + } else { + EXPECT_EQ( + out, + R"({"int64Value":"3","repeatedInt32Value":[2],"boolValue":true,"repeatedInt32Value":[2]})"); + } } } // namespace
diff --git a/third_party/benchmark b/third_party/benchmark index 0baacde..5b7683f 160000 --- a/third_party/benchmark +++ b/third_party/benchmark
@@ -1 +1 @@ -Subproject commit 0baacde3618ca617da95375e0af13ce1baadea47 +Subproject commit 5b7683f49e1e9223cf9927b24f6fd3d6bd82e3f8