| Index: third_party/protobuf/python/google/protobuf/internal/reflection_test.py
|
| ===================================================================
|
| --- third_party/protobuf/python/google/protobuf/internal/reflection_test.py (revision 216642)
|
| +++ third_party/protobuf/python/google/protobuf/internal/reflection_test.py (working copy)
|
| @@ -37,6 +37,7 @@
|
|
|
| __author__ = 'robinson@google.com (Will Robinson)'
|
|
|
| +import gc
|
| import operator
|
| import struct
|
|
|
| @@ -318,15 +319,6 @@
|
| # ...and ensure that the scalar field has returned to its default.
|
| self.assertEqual(0, getattr(composite_field, scalar_field_name))
|
|
|
| - # Finally, ensure that modifications to the old composite field object
|
| - # don't have any effect on the parent. Possible only with the pure-python
|
| - # implementation of the API.
|
| - #
|
| - # (NOTE that when we clear the composite field in the parent, we actually
|
| - # don't recursively clear down the tree. Instead, we just disconnect the
|
| - # cleared composite from the tree.)
|
| - if api_implementation.Type() != 'python':
|
| - return
|
| self.assertTrue(old_composite_field is not composite_field)
|
| setattr(old_composite_field, scalar_field_name, new_val)
|
| self.assertTrue(not composite_field.HasField(scalar_field_name))
|
| @@ -348,8 +340,6 @@
|
| nested.bb = 23
|
|
|
| def testDisconnectingNestedMessageBeforeSettingField(self):
|
| - if api_implementation.Type() != 'python':
|
| - return
|
| proto = unittest_pb2.TestAllTypes()
|
| nested = proto.optional_nested_message
|
| proto.ClearField('optional_nested_message') # Should disconnect from parent
|
| @@ -358,6 +348,64 @@
|
| self.assertTrue(not proto.HasField('optional_nested_message'))
|
| self.assertEqual(0, proto.optional_nested_message.bb)
|
|
|
| + def testGetDefaultMessageAfterDisconnectingDefaultMessage(self):
|
| + proto = unittest_pb2.TestAllTypes()
|
| + nested = proto.optional_nested_message
|
| + proto.ClearField('optional_nested_message')
|
| + del proto
|
| + del nested
|
| + # Force a garbage collect so that the underlying CMessages are freed along
|
| + # with the Messages they point to. This is to make sure we're not deleting
|
| + # default message instances.
|
| + gc.collect()
|
| + proto = unittest_pb2.TestAllTypes()
|
| + nested = proto.optional_nested_message
|
| +
|
| + def testDisconnectingNestedMessageAfterSettingField(self):
|
| + proto = unittest_pb2.TestAllTypes()
|
| + nested = proto.optional_nested_message
|
| + nested.bb = 5
|
| + self.assertTrue(proto.HasField('optional_nested_message'))
|
| + proto.ClearField('optional_nested_message') # Should disconnect from parent
|
| + self.assertEqual(5, nested.bb)
|
| + self.assertEqual(0, proto.optional_nested_message.bb)
|
| + self.assertTrue(nested is not proto.optional_nested_message)
|
| + nested.bb = 23
|
| + self.assertTrue(not proto.HasField('optional_nested_message'))
|
| + self.assertEqual(0, proto.optional_nested_message.bb)
|
| +
|
| + def testDisconnectingNestedMessageBeforeGettingField(self):
|
| + proto = unittest_pb2.TestAllTypes()
|
| + self.assertTrue(not proto.HasField('optional_nested_message'))
|
| + proto.ClearField('optional_nested_message')
|
| + self.assertTrue(not proto.HasField('optional_nested_message'))
|
| +
|
| + def testDisconnectingNestedMessageAfterMerge(self):
|
| + # This test exercises the code path that does not use ReleaseMessage().
|
| + # The underlying fear is that if we use ReleaseMessage() incorrectly,
|
| + # we will have memory leaks. It's hard to check that that doesn't happen,
|
| + # but at least we can exercise that code path to make sure it works.
|
| + proto1 = unittest_pb2.TestAllTypes()
|
| + proto2 = unittest_pb2.TestAllTypes()
|
| + proto2.optional_nested_message.bb = 5
|
| + proto1.MergeFrom(proto2)
|
| + self.assertTrue(proto1.HasField('optional_nested_message'))
|
| + proto1.ClearField('optional_nested_message')
|
| + self.assertTrue(not proto1.HasField('optional_nested_message'))
|
| +
|
| + def testDisconnectingLazyNestedMessage(self):
|
| + # This test exercises releasing a nested message that is lazy. This test
|
| + # only exercises real code in the C++ implementation as Python does not
|
| + # support lazy parsing, but the current C++ implementation results in
|
| + # memory corruption and a crash.
|
| + if api_implementation.Type() != 'python':
|
| + return
|
| + proto = unittest_pb2.TestAllTypes()
|
| + proto.optional_lazy_message.bb = 5
|
| + proto.ClearField('optional_lazy_message')
|
| + del proto
|
| + gc.collect()
|
| +
|
| def testHasBitsWhenModifyingRepeatedFields(self):
|
| # Test nesting when we add an element to a repeated field in a submessage.
|
| proto = unittest_pb2.TestNestedMessageHasBits()
|
| @@ -635,6 +683,77 @@
|
| self.assertEqual(3, proto.BAZ)
|
| self.assertEqual(3, unittest_pb2.TestAllTypes.BAZ)
|
|
|
| + def testEnum_Name(self):
|
| + self.assertEqual('FOREIGN_FOO',
|
| + unittest_pb2.ForeignEnum.Name(unittest_pb2.FOREIGN_FOO))
|
| + self.assertEqual('FOREIGN_BAR',
|
| + unittest_pb2.ForeignEnum.Name(unittest_pb2.FOREIGN_BAR))
|
| + self.assertEqual('FOREIGN_BAZ',
|
| + unittest_pb2.ForeignEnum.Name(unittest_pb2.FOREIGN_BAZ))
|
| + self.assertRaises(ValueError,
|
| + unittest_pb2.ForeignEnum.Name, 11312)
|
| +
|
| + proto = unittest_pb2.TestAllTypes()
|
| + self.assertEqual('FOO',
|
| + proto.NestedEnum.Name(proto.FOO))
|
| + self.assertEqual('FOO',
|
| + unittest_pb2.TestAllTypes.NestedEnum.Name(proto.FOO))
|
| + self.assertEqual('BAR',
|
| + proto.NestedEnum.Name(proto.BAR))
|
| + self.assertEqual('BAR',
|
| + unittest_pb2.TestAllTypes.NestedEnum.Name(proto.BAR))
|
| + self.assertEqual('BAZ',
|
| + proto.NestedEnum.Name(proto.BAZ))
|
| + self.assertEqual('BAZ',
|
| + unittest_pb2.TestAllTypes.NestedEnum.Name(proto.BAZ))
|
| + self.assertRaises(ValueError,
|
| + proto.NestedEnum.Name, 11312)
|
| + self.assertRaises(ValueError,
|
| + unittest_pb2.TestAllTypes.NestedEnum.Name, 11312)
|
| +
|
| + def testEnum_Value(self):
|
| + self.assertEqual(unittest_pb2.FOREIGN_FOO,
|
| + unittest_pb2.ForeignEnum.Value('FOREIGN_FOO'))
|
| + self.assertEqual(unittest_pb2.FOREIGN_BAR,
|
| + unittest_pb2.ForeignEnum.Value('FOREIGN_BAR'))
|
| + self.assertEqual(unittest_pb2.FOREIGN_BAZ,
|
| + unittest_pb2.ForeignEnum.Value('FOREIGN_BAZ'))
|
| + self.assertRaises(ValueError,
|
| + unittest_pb2.ForeignEnum.Value, 'FO')
|
| +
|
| + proto = unittest_pb2.TestAllTypes()
|
| + self.assertEqual(proto.FOO,
|
| + proto.NestedEnum.Value('FOO'))
|
| + self.assertEqual(proto.FOO,
|
| + unittest_pb2.TestAllTypes.NestedEnum.Value('FOO'))
|
| + self.assertEqual(proto.BAR,
|
| + proto.NestedEnum.Value('BAR'))
|
| + self.assertEqual(proto.BAR,
|
| + unittest_pb2.TestAllTypes.NestedEnum.Value('BAR'))
|
| + self.assertEqual(proto.BAZ,
|
| + proto.NestedEnum.Value('BAZ'))
|
| + self.assertEqual(proto.BAZ,
|
| + unittest_pb2.TestAllTypes.NestedEnum.Value('BAZ'))
|
| + self.assertRaises(ValueError,
|
| + proto.NestedEnum.Value, 'Foo')
|
| + self.assertRaises(ValueError,
|
| + unittest_pb2.TestAllTypes.NestedEnum.Value, 'Foo')
|
| +
|
| + def testEnum_KeysAndValues(self):
|
| + self.assertEqual(['FOREIGN_FOO', 'FOREIGN_BAR', 'FOREIGN_BAZ'],
|
| + unittest_pb2.ForeignEnum.keys())
|
| + self.assertEqual([4, 5, 6],
|
| + unittest_pb2.ForeignEnum.values())
|
| + self.assertEqual([('FOREIGN_FOO', 4), ('FOREIGN_BAR', 5),
|
| + ('FOREIGN_BAZ', 6)],
|
| + unittest_pb2.ForeignEnum.items())
|
| +
|
| + proto = unittest_pb2.TestAllTypes()
|
| + self.assertEqual(['FOO', 'BAR', 'BAZ'], proto.NestedEnum.keys())
|
| + self.assertEqual([1, 2, 3], proto.NestedEnum.values())
|
| + self.assertEqual([('FOO', 1), ('BAR', 2), ('BAZ', 3)],
|
| + proto.NestedEnum.items())
|
| +
|
| def testRepeatedScalars(self):
|
| proto = unittest_pb2.TestAllTypes()
|
|
|
| @@ -826,6 +945,35 @@
|
| self.assertEqual(1, len(proto.repeated_nested_message))
|
| self.assertEqual(23, proto.repeated_nested_message[0].bb)
|
|
|
| + def testRepeatedCompositeRemove(self):
|
| + proto = unittest_pb2.TestAllTypes()
|
| +
|
| + self.assertEqual(0, len(proto.repeated_nested_message))
|
| + m0 = proto.repeated_nested_message.add()
|
| + # Need to set some differentiating variable so m0 != m1 != m2:
|
| + m0.bb = len(proto.repeated_nested_message)
|
| + m1 = proto.repeated_nested_message.add()
|
| + m1.bb = len(proto.repeated_nested_message)
|
| + self.assertTrue(m0 != m1)
|
| + m2 = proto.repeated_nested_message.add()
|
| + m2.bb = len(proto.repeated_nested_message)
|
| + self.assertListsEqual([m0, m1, m2], proto.repeated_nested_message)
|
| +
|
| + self.assertEqual(3, len(proto.repeated_nested_message))
|
| + proto.repeated_nested_message.remove(m0)
|
| + self.assertEqual(2, len(proto.repeated_nested_message))
|
| + self.assertEqual(m1, proto.repeated_nested_message[0])
|
| + self.assertEqual(m2, proto.repeated_nested_message[1])
|
| +
|
| + # Removing m0 again or removing None should raise error
|
| + self.assertRaises(ValueError, proto.repeated_nested_message.remove, m0)
|
| + self.assertRaises(ValueError, proto.repeated_nested_message.remove, None)
|
| + self.assertEqual(2, len(proto.repeated_nested_message))
|
| +
|
| + proto.repeated_nested_message.remove(m2)
|
| + self.assertEqual(1, len(proto.repeated_nested_message))
|
| + self.assertEqual(m1, proto.repeated_nested_message[0])
|
| +
|
| def testHandWrittenReflection(self):
|
| # Hand written extensions are only supported by the pure-Python
|
| # implementation of the API.
|
| @@ -856,6 +1004,68 @@
|
| self.assertEqual(23, myproto_instance.foo_field)
|
| self.assertTrue(myproto_instance.HasField('foo_field'))
|
|
|
| + def testDescriptorProtoSupport(self):
|
| + # Hand written descriptors/reflection are only supported by the pure-Python
|
| + # implementation of the API.
|
| + if api_implementation.Type() != 'python':
|
| + return
|
| +
|
| + def AddDescriptorField(proto, field_name, field_type):
|
| + AddDescriptorField.field_index += 1
|
| + new_field = proto.field.add()
|
| + new_field.name = field_name
|
| + new_field.type = field_type
|
| + new_field.number = AddDescriptorField.field_index
|
| + new_field.label = descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL
|
| +
|
| + AddDescriptorField.field_index = 0
|
| +
|
| + desc_proto = descriptor_pb2.DescriptorProto()
|
| + desc_proto.name = 'Car'
|
| + fdp = descriptor_pb2.FieldDescriptorProto
|
| + AddDescriptorField(desc_proto, 'name', fdp.TYPE_STRING)
|
| + AddDescriptorField(desc_proto, 'year', fdp.TYPE_INT64)
|
| + AddDescriptorField(desc_proto, 'automatic', fdp.TYPE_BOOL)
|
| + AddDescriptorField(desc_proto, 'price', fdp.TYPE_DOUBLE)
|
| + # Add a repeated field
|
| + AddDescriptorField.field_index += 1
|
| + new_field = desc_proto.field.add()
|
| + new_field.name = 'owners'
|
| + new_field.type = fdp.TYPE_STRING
|
| + new_field.number = AddDescriptorField.field_index
|
| + new_field.label = descriptor_pb2.FieldDescriptorProto.LABEL_REPEATED
|
| +
|
| + desc = descriptor.MakeDescriptor(desc_proto)
|
| + self.assertTrue(desc.fields_by_name.has_key('name'))
|
| + self.assertTrue(desc.fields_by_name.has_key('year'))
|
| + self.assertTrue(desc.fields_by_name.has_key('automatic'))
|
| + self.assertTrue(desc.fields_by_name.has_key('price'))
|
| + self.assertTrue(desc.fields_by_name.has_key('owners'))
|
| +
|
| + class CarMessage(message.Message):
|
| + __metaclass__ = reflection.GeneratedProtocolMessageType
|
| + DESCRIPTOR = desc
|
| +
|
| + prius = CarMessage()
|
| + prius.name = 'prius'
|
| + prius.year = 2010
|
| + prius.automatic = True
|
| + prius.price = 25134.75
|
| + prius.owners.extend(['bob', 'susan'])
|
| +
|
| + serialized_prius = prius.SerializeToString()
|
| + new_prius = reflection.ParseMessage(desc, serialized_prius)
|
| + self.assertTrue(new_prius is not prius)
|
| + self.assertEqual(prius, new_prius)
|
| +
|
| + # these are unnecessary assuming message equality works as advertised but
|
| + # explicitly check to be safe since we're mucking about in metaclass foo
|
| + self.assertEqual(prius.name, new_prius.name)
|
| + self.assertEqual(prius.year, new_prius.year)
|
| + self.assertEqual(prius.automatic, new_prius.automatic)
|
| + self.assertEqual(prius.price, new_prius.price)
|
| + self.assertEqual(prius.owners, new_prius.owners)
|
| +
|
| def testTopLevelExtensionsForOptionalScalar(self):
|
| extendee_proto = unittest_pb2.TestAllExtensions()
|
| extension = unittest_pb2.optional_int32_extension
|
| @@ -1243,7 +1453,12 @@
|
|
|
| def testClear(self):
|
| proto = unittest_pb2.TestAllTypes()
|
| - test_util.SetAllFields(proto)
|
| + # C++ implementation does not support lazy fields right now so leave it
|
| + # out for now.
|
| + if api_implementation.Type() == 'python':
|
| + test_util.SetAllFields(proto)
|
| + else:
|
| + test_util.SetAllNonLazyFields(proto)
|
| # Clear the message.
|
| proto.Clear()
|
| self.assertEquals(proto.ByteSize(), 0)
|
| @@ -1259,6 +1474,33 @@
|
| empty_proto = unittest_pb2.TestAllExtensions()
|
| self.assertEquals(proto, empty_proto)
|
|
|
| + def testDisconnectingBeforeClear(self):
|
| + proto = unittest_pb2.TestAllTypes()
|
| + nested = proto.optional_nested_message
|
| + proto.Clear()
|
| + self.assertTrue(nested is not proto.optional_nested_message)
|
| + nested.bb = 23
|
| + self.assertTrue(not proto.HasField('optional_nested_message'))
|
| + self.assertEqual(0, proto.optional_nested_message.bb)
|
| +
|
| + proto = unittest_pb2.TestAllTypes()
|
| + nested = proto.optional_nested_message
|
| + nested.bb = 5
|
| + foreign = proto.optional_foreign_message
|
| + foreign.c = 6
|
| +
|
| + proto.Clear()
|
| + self.assertTrue(nested is not proto.optional_nested_message)
|
| + self.assertTrue(foreign is not proto.optional_foreign_message)
|
| + self.assertEqual(5, nested.bb)
|
| + self.assertEqual(6, foreign.c)
|
| + nested.bb = 15
|
| + foreign.c = 16
|
| + self.assertTrue(not proto.HasField('optional_nested_message'))
|
| + self.assertEqual(0, proto.optional_nested_message.bb)
|
| + self.assertTrue(not proto.HasField('optional_foreign_message'))
|
| + self.assertEqual(0, proto.optional_foreign_message.c)
|
| +
|
| def assertInitialized(self, proto):
|
| self.assertTrue(proto.IsInitialized())
|
| # Neither method should raise an exception.
|
| @@ -1408,7 +1650,7 @@
|
| unicode_decode_failed = False
|
| try:
|
| message2.MergeFromString(bytes)
|
| - except UnicodeDecodeError, e:
|
| + except UnicodeDecodeError as e:
|
| unicode_decode_failed = True
|
| string_field = message2.str
|
| self.assertTrue(unicode_decode_failed or type(string_field) == str)
|
| @@ -2119,7 +2361,7 @@
|
| """This method checks if the excpetion type and message are as expected."""
|
| try:
|
| callable_obj()
|
| - except exc_class, ex:
|
| + except exc_class as ex:
|
| # Check if the exception message is the right one.
|
| self.assertEqual(exception, str(ex))
|
| return
|
| @@ -2131,15 +2373,22 @@
|
| self._CheckRaises(
|
| message.EncodeError,
|
| proto.SerializeToString,
|
| - 'Message is missing required fields: a,b,c')
|
| + 'Message protobuf_unittest.TestRequired is missing required fields: '
|
| + 'a,b,c')
|
| # Shouldn't raise exceptions.
|
| partial = proto.SerializePartialToString()
|
|
|
| + proto2 = unittest_pb2.TestRequired()
|
| + self.assertFalse(proto2.HasField('a'))
|
| + # proto2 ParseFromString does not check that required fields are set.
|
| + proto2.ParseFromString(partial)
|
| + self.assertFalse(proto2.HasField('a'))
|
| +
|
| proto.a = 1
|
| self._CheckRaises(
|
| message.EncodeError,
|
| proto.SerializeToString,
|
| - 'Message is missing required fields: b,c')
|
| + 'Message protobuf_unittest.TestRequired is missing required fields: b,c')
|
| # Shouldn't raise exceptions.
|
| partial = proto.SerializePartialToString()
|
|
|
| @@ -2147,7 +2396,7 @@
|
| self._CheckRaises(
|
| message.EncodeError,
|
| proto.SerializeToString,
|
| - 'Message is missing required fields: c')
|
| + 'Message protobuf_unittest.TestRequired is missing required fields: c')
|
| # Shouldn't raise exceptions.
|
| partial = proto.SerializePartialToString()
|
|
|
| @@ -2176,7 +2425,8 @@
|
| self._CheckRaises(
|
| message.EncodeError,
|
| proto.SerializeToString,
|
| - 'Message is missing required fields: '
|
| + 'Message protobuf_unittest.TestRequiredForeign '
|
| + 'is missing required fields: '
|
| 'optional_message.b,optional_message.c')
|
|
|
| proto.optional_message.b = 2
|
| @@ -2188,7 +2438,7 @@
|
| self._CheckRaises(
|
| message.EncodeError,
|
| proto.SerializeToString,
|
| - 'Message is missing required fields: '
|
| + 'Message protobuf_unittest.TestRequiredForeign is missing required fields: '
|
| 'repeated_message[0].b,repeated_message[0].c,'
|
| 'repeated_message[1].a,repeated_message[1].c')
|
|
|
|
|