Skip to content

Commit

Permalink
Add test cases for empty map entries for text format in Python.
Browse files Browse the repository at this point in the history
This is just part of an effort at locking down (and understand well) how map
entries are serialized into textproto when they have empty fields.

Right now the C++ behaviour for DynamicMessages is that for implicit-presence
(i.e. "proto3") fields, the empty MapEntry fields are not serialized even if
explicitly set. For example, `value: ""` would not show up in textproto
serialization for proto3 MapEntry messages. This contrasts with C++ map
reflection behaviour, because C++ MapEntry messages are always generated with
hasbits (even if they are declared in a proto3 file and have implicit presence
according to their descriptors).

For this Python test, the DynamicMessage fallback path was triggered because
the implementation of the C++ proto was not found. When python is lacking in
implementation, it calls DynamicMessage which respects field presence, even for
map entries. If the corresponding `map_unittest_cc_proto` is linked, this test
actually fails, because the C++ MapEntry implementation, which is always
generated with hasbits even for implicit presence, is used.

PiperOrigin-RevId: 681944020
tonyliaoss authored and copybara-github committed Oct 3, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent fa858b8 commit d4a32bb
Showing 1 changed file with 67 additions and 0 deletions.
67 changes: 67 additions & 0 deletions python/google/protobuf/internal/text_format_test.py
Original file line number Diff line number Diff line change
@@ -1179,6 +1179,73 @@ def testParseLinesGolden(self):
test_util.SetAllFields(message)
self.assertEqual(message, parsed_message)

def testPrintMapEmptyKeys(self):
message = map_unittest_pb2.TestMap()

message.map_int32_int32[0] = 123
message.map_int64_int64[0] = 2**33
message.map_uint32_uint32[0] = 123
message.map_uint64_uint64[0] = 2**33
message.map_string_string[''] = 'world'
message.map_int32_foreign_message[0].c = 111
self.CompareToGoldenText(
text_format.MessageToString(message),
'map_int32_int32 {\n'
' value: 123\n'
'}\n'
'map_int64_int64 {\n'
' value: 8589934592\n'
'}\n'
'map_uint32_uint32 {\n'
' value: 123\n'
'}\n'
'map_uint64_uint64 {\n'
' value: 8589934592\n'
'}\n'
'map_string_string {\n'
' value: "world"\n'
'}\n'
'map_int32_foreign_message {\n'
' value {\n'
' c: 111\n'
' }\n'
'}\n',
)

def testPrintMapEmptyValues(self):
message = map_unittest_pb2.TestMap()

message.map_int32_int32[-123] = 0
message.map_int64_int64[-(2**33)] = 0
message.map_uint32_uint32[123] = 0
message.map_uint64_uint64[2**33] = 0
message.map_string_string['hello'] = ''
message.map_int32_foreign_message[111].c = 0
self.CompareToGoldenText(
text_format.MessageToString(message),
'map_int32_int32 {\n'
' key: -123\n'
'}\n'
'map_int64_int64 {\n'
' key: -8589934592\n'
'}\n'
'map_uint32_uint32 {\n'
' key: 123\n'
'}\n'
'map_uint64_uint64 {\n'
' key: 8589934592\n'
'}\n'
'map_string_string {\n'
' key: "hello"\n'
'}\n'
'map_int32_foreign_message {\n'
' key: 111\n'
' value {\n'
' c: 0\n'
' }\n'
'}\n',
)

def testPrintMap(self):
message = map_unittest_pb2.TestMap()

0 comments on commit d4a32bb

Please sign in to comment.