Index: third_party/protobuf/python/google/protobuf/internal/unknown_fields_test.py |
diff --git a/third_party/protobuf/python/google/protobuf/internal/unknown_fields_test.py b/third_party/protobuf/python/google/protobuf/internal/unknown_fields_test.py |
index 84073f1c5344f934d4def999fa209700fc7dd39d..d614eaa8744f79cab2c646e454e896cbd09e48ab 100755 |
--- a/third_party/protobuf/python/google/protobuf/internal/unknown_fields_test.py |
+++ b/third_party/protobuf/python/google/protobuf/internal/unknown_fields_test.py |
@@ -47,16 +47,20 @@ from google.protobuf.internal import encoder |
from google.protobuf.internal import message_set_extensions_pb2 |
from google.protobuf.internal import missing_enum_values_pb2 |
from google.protobuf.internal import test_util |
+from google.protobuf.internal import testing_refleaks |
from google.protobuf.internal import type_checkers |
+BaseTestCase = testing_refleaks.BaseTestCase |
+ |
+ |
def SkipIfCppImplementation(func): |
return unittest.skipIf( |
api_implementation.Type() == 'cpp' and api_implementation.Version() == 2, |
'C++ implementation does not expose unknown fields to Python')(func) |
-class UnknownFieldsTest(unittest.TestCase): |
+class UnknownFieldsTest(BaseTestCase): |
def setUp(self): |
self.descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR |
@@ -140,7 +144,7 @@ class UnknownFieldsTest(unittest.TestCase): |
b'', message.repeated_nested_message[0].SerializeToString()) |
-class UnknownFieldsAccessorsTest(unittest.TestCase): |
+class UnknownFieldsAccessorsTest(BaseTestCase): |
def setUp(self): |
self.descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR |
@@ -149,21 +153,18 @@ class UnknownFieldsAccessorsTest(unittest.TestCase): |
self.all_fields_data = self.all_fields.SerializeToString() |
self.empty_message = unittest_pb2.TestEmptyMessage() |
self.empty_message.ParseFromString(self.all_fields_data) |
- if api_implementation.Type() != 'cpp': |
- # _unknown_fields is an implementation detail. |
- self.unknown_fields = self.empty_message._unknown_fields |
- # All the tests that use GetField() check an implementation detail of the |
- # Python implementation, which stores unknown fields as serialized strings. |
- # These tests are skipped by the C++ implementation: it's enough to check that |
- # the message is correctly serialized. |
+ # GetUnknownField() checks a detail of the Python implementation, which stores |
+ # unknown fields as serialized strings. It cannot be used by the C++ |
+ # implementation: it's enough to check that the message is correctly |
+ # serialized. |
- def GetField(self, name): |
+ def GetUnknownField(self, name): |
field_descriptor = self.descriptor.fields_by_name[name] |
wire_type = type_checkers.FIELD_TYPE_TO_WIRE_TYPE[field_descriptor.type] |
field_tag = encoder.TagBytes(field_descriptor.number, wire_type) |
result_dict = {} |
- for tag_bytes, value in self.unknown_fields: |
+ for tag_bytes, value in self.empty_message._unknown_fields: |
if tag_bytes == field_tag: |
decoder = unittest_pb2.TestAllTypes._decoders_by_tag[tag_bytes][0] |
decoder(value, 0, len(value), self.all_fields, result_dict) |
@@ -171,37 +172,37 @@ class UnknownFieldsAccessorsTest(unittest.TestCase): |
@SkipIfCppImplementation |
def testEnum(self): |
- value = self.GetField('optional_nested_enum') |
+ value = self.GetUnknownField('optional_nested_enum') |
self.assertEqual(self.all_fields.optional_nested_enum, value) |
@SkipIfCppImplementation |
def testRepeatedEnum(self): |
- value = self.GetField('repeated_nested_enum') |
+ value = self.GetUnknownField('repeated_nested_enum') |
self.assertEqual(self.all_fields.repeated_nested_enum, value) |
@SkipIfCppImplementation |
def testVarint(self): |
- value = self.GetField('optional_int32') |
+ value = self.GetUnknownField('optional_int32') |
self.assertEqual(self.all_fields.optional_int32, value) |
@SkipIfCppImplementation |
def testFixed32(self): |
- value = self.GetField('optional_fixed32') |
+ value = self.GetUnknownField('optional_fixed32') |
self.assertEqual(self.all_fields.optional_fixed32, value) |
@SkipIfCppImplementation |
def testFixed64(self): |
- value = self.GetField('optional_fixed64') |
+ value = self.GetUnknownField('optional_fixed64') |
self.assertEqual(self.all_fields.optional_fixed64, value) |
@SkipIfCppImplementation |
def testLengthDelimited(self): |
- value = self.GetField('optional_string') |
+ value = self.GetUnknownField('optional_string') |
self.assertEqual(self.all_fields.optional_string, value) |
@SkipIfCppImplementation |
def testGroup(self): |
- value = self.GetField('optionalgroup') |
+ value = self.GetUnknownField('optionalgroup') |
self.assertEqual(self.all_fields.optionalgroup, value) |
def testCopyFrom(self): |
@@ -241,43 +242,41 @@ class UnknownFieldsAccessorsTest(unittest.TestCase): |
self.assertEqual(message.SerializeToString(), self.all_fields_data) |
-class UnknownEnumValuesTest(unittest.TestCase): |
+class UnknownEnumValuesTest(BaseTestCase): |
def setUp(self): |
self.descriptor = missing_enum_values_pb2.TestEnumValues.DESCRIPTOR |
self.message = missing_enum_values_pb2.TestEnumValues() |
+ # TestEnumValues.ZERO = 0, but does not exist in the other NestedEnum. |
self.message.optional_nested_enum = ( |
- missing_enum_values_pb2.TestEnumValues.ZERO) |
+ missing_enum_values_pb2.TestEnumValues.ZERO) |
self.message.repeated_nested_enum.extend([ |
- missing_enum_values_pb2.TestEnumValues.ZERO, |
- missing_enum_values_pb2.TestEnumValues.ONE, |
- ]) |
+ missing_enum_values_pb2.TestEnumValues.ZERO, |
+ missing_enum_values_pb2.TestEnumValues.ONE, |
+ ]) |
self.message.packed_nested_enum.extend([ |
- missing_enum_values_pb2.TestEnumValues.ZERO, |
- missing_enum_values_pb2.TestEnumValues.ONE, |
- ]) |
+ missing_enum_values_pb2.TestEnumValues.ZERO, |
+ missing_enum_values_pb2.TestEnumValues.ONE, |
+ ]) |
self.message_data = self.message.SerializeToString() |
self.missing_message = missing_enum_values_pb2.TestMissingEnumValues() |
self.missing_message.ParseFromString(self.message_data) |
- if api_implementation.Type() != 'cpp': |
- # _unknown_fields is an implementation detail. |
- self.unknown_fields = self.missing_message._unknown_fields |
- # All the tests that use GetField() check an implementation detail of the |
- # Python implementation, which stores unknown fields as serialized strings. |
- # These tests are skipped by the C++ implementation: it's enough to check that |
- # the message is correctly serialized. |
+ # GetUnknownField() checks a detail of the Python implementation, which stores |
+ # unknown fields as serialized strings. It cannot be used by the C++ |
+ # implementation: it's enough to check that the message is correctly |
+ # serialized. |
- def GetField(self, name): |
+ def GetUnknownField(self, name): |
field_descriptor = self.descriptor.fields_by_name[name] |
wire_type = type_checkers.FIELD_TYPE_TO_WIRE_TYPE[field_descriptor.type] |
field_tag = encoder.TagBytes(field_descriptor.number, wire_type) |
result_dict = {} |
- for tag_bytes, value in self.unknown_fields: |
+ for tag_bytes, value in self.missing_message._unknown_fields: |
if tag_bytes == field_tag: |
decoder = missing_enum_values_pb2.TestEnumValues._decoders_by_tag[ |
- tag_bytes][0] |
+ tag_bytes][0] |
decoder(value, 0, len(value), self.message, result_dict) |
return result_dict[field_descriptor] |
@@ -294,21 +293,39 @@ class UnknownEnumValuesTest(unittest.TestCase): |
# default value. |
self.assertEqual(missing.optional_nested_enum, 0) |
- @SkipIfCppImplementation |
def testUnknownEnumValue(self): |
+ if api_implementation.Type() == 'cpp': |
+ # The CPP implementation of protos (wrongly) allows unknown enum values |
+ # for proto2. |
+ self.assertTrue(self.missing_message.HasField('optional_nested_enum')) |
+ self.assertEqual(self.message.optional_nested_enum, |
+ self.missing_message.optional_nested_enum) |
+ else: |
+ # On the other hand, the Python implementation considers unknown values |
+ # as unknown fields. This is the correct behavior. |
+ self.assertFalse(self.missing_message.HasField('optional_nested_enum')) |
+ value = self.GetUnknownField('optional_nested_enum') |
+ self.assertEqual(self.message.optional_nested_enum, value) |
+ self.missing_message.ClearField('optional_nested_enum') |
self.assertFalse(self.missing_message.HasField('optional_nested_enum')) |
- value = self.GetField('optional_nested_enum') |
- self.assertEqual(self.message.optional_nested_enum, value) |
- @SkipIfCppImplementation |
def testUnknownRepeatedEnumValue(self): |
- value = self.GetField('repeated_nested_enum') |
- self.assertEqual(self.message.repeated_nested_enum, value) |
+ if api_implementation.Type() == 'cpp': |
+ # For repeated enums, both implementations agree. |
+ self.assertEqual([], self.missing_message.repeated_nested_enum) |
+ else: |
+ self.assertEqual([], self.missing_message.repeated_nested_enum) |
+ value = self.GetUnknownField('repeated_nested_enum') |
+ self.assertEqual(self.message.repeated_nested_enum, value) |
- @SkipIfCppImplementation |
def testUnknownPackedEnumValue(self): |
- value = self.GetField('packed_nested_enum') |
- self.assertEqual(self.message.packed_nested_enum, value) |
+ if api_implementation.Type() == 'cpp': |
+ # For repeated enums, both implementations agree. |
+ self.assertEqual([], self.missing_message.packed_nested_enum) |
+ else: |
+ self.assertEqual([], self.missing_message.packed_nested_enum) |
+ value = self.GetUnknownField('packed_nested_enum') |
+ self.assertEqual(self.message.packed_nested_enum, value) |
def testRoundTrip(self): |
new_message = missing_enum_values_pb2.TestEnumValues() |