Index: third_party/protobuf/python/google/protobuf/internal/descriptor_test.py |
diff --git a/third_party/protobuf/python/google/protobuf/internal/descriptor_test.py b/third_party/protobuf/python/google/protobuf/internal/descriptor_test.py |
index c74f882e7821098c3bfb72a387be7291e838b527..fee09a5627f231d63a7815ca25ddaff7ec3a3aef 100755 |
--- a/third_party/protobuf/python/google/protobuf/internal/descriptor_test.py |
+++ b/third_party/protobuf/python/google/protobuf/internal/descriptor_test.py |
@@ -1,8 +1,8 @@ |
-#! /usr/bin/python |
+#! /usr/bin/env python |
# |
# Protocol Buffers - Google's data interchange format |
# Copyright 2008 Google Inc. All rights reserved. |
-# http://code.google.com/p/protobuf/ |
+# https://developers.google.com/protocol-buffers/ |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions are |
@@ -34,12 +34,21 @@ |
__author__ = 'robinson@google.com (Will Robinson)' |
-import unittest |
+import sys |
+ |
+try: |
+ import unittest2 as unittest |
+except ImportError: |
+ import unittest |
from google.protobuf import unittest_custom_options_pb2 |
from google.protobuf import unittest_import_pb2 |
from google.protobuf import unittest_pb2 |
from google.protobuf import descriptor_pb2 |
+from google.protobuf.internal import api_implementation |
+from google.protobuf.internal import test_util |
from google.protobuf import descriptor |
+from google.protobuf import descriptor_pool |
+from google.protobuf import symbol_database |
from google.protobuf import text_format |
@@ -51,41 +60,28 @@ name: 'TestEmptyMessage' |
class DescriptorTest(unittest.TestCase): |
def setUp(self): |
- self.my_file = descriptor.FileDescriptor( |
+ file_proto = descriptor_pb2.FileDescriptorProto( |
name='some/filename/some.proto', |
- package='protobuf_unittest' |
- ) |
- self.my_enum = descriptor.EnumDescriptor( |
- name='ForeignEnum', |
- full_name='protobuf_unittest.ForeignEnum', |
- filename=None, |
- file=self.my_file, |
- values=[ |
- descriptor.EnumValueDescriptor(name='FOREIGN_FOO', index=0, number=4), |
- descriptor.EnumValueDescriptor(name='FOREIGN_BAR', index=1, number=5), |
- descriptor.EnumValueDescriptor(name='FOREIGN_BAZ', index=2, number=6), |
- ]) |
- self.my_message = descriptor.Descriptor( |
- name='NestedMessage', |
- full_name='protobuf_unittest.TestAllTypes.NestedMessage', |
- filename=None, |
- file=self.my_file, |
- containing_type=None, |
- fields=[ |
- descriptor.FieldDescriptor( |
- name='bb', |
- full_name='protobuf_unittest.TestAllTypes.NestedMessage.bb', |
- index=0, number=1, |
- type=5, cpp_type=1, label=1, |
- has_default_value=False, default_value=0, |
- message_type=None, enum_type=None, containing_type=None, |
- is_extension=False, extension_scope=None), |
- ], |
- nested_types=[], |
- enum_types=[ |
- self.my_enum, |
- ], |
- extensions=[]) |
+ package='protobuf_unittest') |
+ message_proto = file_proto.message_type.add( |
+ name='NestedMessage') |
+ message_proto.field.add( |
+ name='bb', |
+ number=1, |
+ type=descriptor_pb2.FieldDescriptorProto.TYPE_INT32, |
+ label=descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL) |
+ enum_proto = message_proto.enum_type.add( |
+ name='ForeignEnum') |
+ enum_proto.value.add(name='FOREIGN_FOO', number=4) |
+ enum_proto.value.add(name='FOREIGN_BAR', number=5) |
+ enum_proto.value.add(name='FOREIGN_BAZ', number=6) |
+ |
+ self.pool = self.GetDescriptorPool() |
+ self.pool.Add(file_proto) |
+ self.my_file = self.pool.FindFileByName(file_proto.name) |
+ self.my_message = self.my_file.message_types_by_name[message_proto.name] |
+ self.my_enum = self.my_message.enum_types_by_name[enum_proto.name] |
+ |
self.my_method = descriptor.MethodDescriptor( |
name='Bar', |
full_name='protobuf_unittest.TestService.Bar', |
@@ -102,6 +98,9 @@ class DescriptorTest(unittest.TestCase): |
self.my_method |
]) |
+ def GetDescriptorPool(self): |
+ return symbol_database.Default().pool |
+ |
def testEnumValueName(self): |
self.assertEqual(self.my_message.EnumValueName('ForeignEnum', 4), |
'FOREIGN_FOO') |
@@ -173,6 +172,11 @@ class DescriptorTest(unittest.TestCase): |
self.assertEqual(unittest_custom_options_pb2.METHODOPT1_VAL2, |
method_options.Extensions[method_opt1]) |
+ message_descriptor = ( |
+ unittest_custom_options_pb2.DummyMessageContainingEnum.DESCRIPTOR) |
+ self.assertTrue(file_descriptor.has_options) |
+ self.assertFalse(message_descriptor.has_options) |
+ |
def testDifferentCustomOptionTypes(self): |
kint32min = -2**31 |
kint64min = -2**63 |
@@ -244,7 +248,7 @@ class DescriptorTest(unittest.TestCase): |
unittest_custom_options_pb2.double_opt]) |
self.assertEqual("Hello, \"World\"", message_options.Extensions[ |
unittest_custom_options_pb2.string_opt]) |
- self.assertEqual("Hello\0World", message_options.Extensions[ |
+ self.assertEqual(b"Hello\0World", message_options.Extensions[ |
unittest_custom_options_pb2.bytes_opt]) |
dummy_enum = unittest_custom_options_pb2.DummyMessageContainingEnum |
self.assertEqual( |
@@ -393,6 +397,127 @@ class DescriptorTest(unittest.TestCase): |
def testFileDescriptor(self): |
self.assertEqual(self.my_file.name, 'some/filename/some.proto') |
self.assertEqual(self.my_file.package, 'protobuf_unittest') |
+ self.assertEqual(self.my_file.pool, self.pool) |
+ # Generated modules also belong to the default pool. |
+ self.assertEqual(unittest_pb2.DESCRIPTOR.pool, descriptor_pool.Default()) |
+ |
+ @unittest.skipIf( |
+ api_implementation.Type() != 'cpp' or api_implementation.Version() != 2, |
+ 'Immutability of descriptors is only enforced in v2 implementation') |
+ def testImmutableCppDescriptor(self): |
+ message_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR |
+ with self.assertRaises(AttributeError): |
+ message_descriptor.fields_by_name = None |
+ with self.assertRaises(TypeError): |
+ message_descriptor.fields_by_name['Another'] = None |
+ with self.assertRaises(TypeError): |
+ message_descriptor.fields.append(None) |
+ |
+ |
+class NewDescriptorTest(DescriptorTest): |
+ """Redo the same tests as above, but with a separate DescriptorPool.""" |
+ |
+ def GetDescriptorPool(self): |
+ return descriptor_pool.DescriptorPool() |
+ |
+ |
+class GeneratedDescriptorTest(unittest.TestCase): |
+ """Tests for the properties of descriptors in generated code.""" |
+ |
+ def CheckMessageDescriptor(self, message_descriptor): |
+ # Basic properties |
+ self.assertEqual(message_descriptor.name, 'TestAllTypes') |
+ self.assertEqual(message_descriptor.full_name, |
+ 'protobuf_unittest.TestAllTypes') |
+ # Test equality and hashability |
+ self.assertEqual(message_descriptor, message_descriptor) |
+ self.assertEqual(message_descriptor.fields[0].containing_type, |
+ message_descriptor) |
+ self.assertIn(message_descriptor, [message_descriptor]) |
+ self.assertIn(message_descriptor, {message_descriptor: None}) |
+ # Test field containers |
+ self.CheckDescriptorSequence(message_descriptor.fields) |
+ self.CheckDescriptorMapping(message_descriptor.fields_by_name) |
+ self.CheckDescriptorMapping(message_descriptor.fields_by_number) |
+ self.CheckDescriptorMapping(message_descriptor.fields_by_camelcase_name) |
+ |
+ def CheckFieldDescriptor(self, field_descriptor): |
+ # Basic properties |
+ self.assertEqual(field_descriptor.name, 'optional_int32') |
+ self.assertEqual(field_descriptor.camelcase_name, 'optionalInt32') |
+ self.assertEqual(field_descriptor.full_name, |
+ 'protobuf_unittest.TestAllTypes.optional_int32') |
+ self.assertEqual(field_descriptor.containing_type.name, 'TestAllTypes') |
+ # Test equality and hashability |
+ self.assertEqual(field_descriptor, field_descriptor) |
+ self.assertEqual( |
+ field_descriptor.containing_type.fields_by_name['optional_int32'], |
+ field_descriptor) |
+ self.assertEqual( |
+ field_descriptor.containing_type.fields_by_camelcase_name[ |
+ 'optionalInt32'], |
+ field_descriptor) |
+ self.assertIn(field_descriptor, [field_descriptor]) |
+ self.assertIn(field_descriptor, {field_descriptor: None}) |
+ |
+ def CheckDescriptorSequence(self, sequence): |
+ # Verifies that a property like 'messageDescriptor.fields' has all the |
+ # properties of an immutable abc.Sequence. |
+ self.assertGreater(len(sequence), 0) # Sized |
+ self.assertEqual(len(sequence), len(list(sequence))) # Iterable |
+ item = sequence[0] |
+ self.assertEqual(item, sequence[0]) |
+ self.assertIn(item, sequence) # Container |
+ self.assertEqual(sequence.index(item), 0) |
+ self.assertEqual(sequence.count(item), 1) |
+ reversed_iterator = reversed(sequence) |
+ self.assertEqual(list(reversed_iterator), list(sequence)[::-1]) |
+ self.assertRaises(StopIteration, next, reversed_iterator) |
+ |
+ def CheckDescriptorMapping(self, mapping): |
+ # Verifies that a property like 'messageDescriptor.fields' has all the |
+ # properties of an immutable abc.Mapping. |
+ self.assertGreater(len(mapping), 0) # Sized |
+ self.assertEqual(len(mapping), len(list(mapping))) # Iterable |
+ if sys.version_info >= (3,): |
+ key, item = next(iter(mapping.items())) |
+ else: |
+ key, item = mapping.items()[0] |
+ self.assertIn(key, mapping) # Container |
+ self.assertEqual(mapping.get(key), item) |
+ # keys(), iterkeys() &co |
+ item = (next(iter(mapping.keys())), next(iter(mapping.values()))) |
+ self.assertEqual(item, next(iter(mapping.items()))) |
+ if sys.version_info < (3,): |
+ def CheckItems(seq, iterator): |
+ self.assertEqual(next(iterator), seq[0]) |
+ self.assertEqual(list(iterator), seq[1:]) |
+ CheckItems(mapping.keys(), mapping.iterkeys()) |
+ CheckItems(mapping.values(), mapping.itervalues()) |
+ CheckItems(mapping.items(), mapping.iteritems()) |
+ |
+ def testDescriptor(self): |
+ message_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR |
+ self.CheckMessageDescriptor(message_descriptor) |
+ field_descriptor = message_descriptor.fields_by_name['optional_int32'] |
+ self.CheckFieldDescriptor(field_descriptor) |
+ field_descriptor = message_descriptor.fields_by_camelcase_name[ |
+ 'optionalInt32'] |
+ self.CheckFieldDescriptor(field_descriptor) |
+ |
+ def testCppDescriptorContainer(self): |
+ # Check that the collection is still valid even if the parent disappeared. |
+ enum = unittest_pb2.TestAllTypes.DESCRIPTOR.enum_types_by_name['NestedEnum'] |
+ values = enum.values |
+ del enum |
+ self.assertEqual('FOO', values[0].name) |
+ |
+ def testCppDescriptorContainer_Iterator(self): |
+ # Same test with the iterator |
+ enum = unittest_pb2.TestAllTypes.DESCRIPTOR.enum_types_by_name['NestedEnum'] |
+ values_iter = iter(enum.values) |
+ del enum |
+ self.assertEqual('FOO', next(values_iter).name) |
class DescriptorCopyToProtoTest(unittest.TestCase): |
@@ -530,47 +655,49 @@ class DescriptorCopyToProtoTest(unittest.TestCase): |
descriptor_pb2.DescriptorProto, |
TEST_MESSAGE_WITH_SEVERAL_EXTENSIONS_ASCII) |
- def testCopyToProto_FileDescriptor(self): |
- UNITTEST_IMPORT_FILE_DESCRIPTOR_ASCII = (""" |
- name: 'google/protobuf/unittest_import.proto' |
- package: 'protobuf_unittest_import' |
- dependency: 'google/protobuf/unittest_import_public.proto' |
- message_type: < |
- name: 'ImportMessage' |
- field: < |
- name: 'd' |
- number: 1 |
- label: 1 # Optional |
- type: 5 # TYPE_INT32 |
- > |
- > |
- """ + |
- """enum_type: < |
- name: 'ImportEnum' |
- value: < |
- name: 'IMPORT_FOO' |
- number: 7 |
- > |
- value: < |
- name: 'IMPORT_BAR' |
- number: 8 |
- > |
- value: < |
- name: 'IMPORT_BAZ' |
- number: 9 |
- > |
- > |
- options: < |
- java_package: 'com.google.protobuf.test' |
- optimize_for: 1 # SPEED |
- > |
- public_dependency: 0 |
- """) |
- |
- self._InternalTestCopyToProto( |
- unittest_import_pb2.DESCRIPTOR, |
- descriptor_pb2.FileDescriptorProto, |
- UNITTEST_IMPORT_FILE_DESCRIPTOR_ASCII) |
+ # Disable this test so we can make changes to the proto file. |
+ # TODO(xiaofeng): Enable this test after cl/55530659 is submitted. |
+ # |
+ # def testCopyToProto_FileDescriptor(self): |
+ # UNITTEST_IMPORT_FILE_DESCRIPTOR_ASCII = (""" |
+ # name: 'google/protobuf/unittest_import.proto' |
+ # package: 'protobuf_unittest_import' |
+ # dependency: 'google/protobuf/unittest_import_public.proto' |
+ # message_type: < |
+ # name: 'ImportMessage' |
+ # field: < |
+ # name: 'd' |
+ # number: 1 |
+ # label: 1 # Optional |
+ # type: 5 # TYPE_INT32 |
+ # > |
+ # > |
+ # """ + |
+ # """enum_type: < |
+ # name: 'ImportEnum' |
+ # value: < |
+ # name: 'IMPORT_FOO' |
+ # number: 7 |
+ # > |
+ # value: < |
+ # name: 'IMPORT_BAR' |
+ # number: 8 |
+ # > |
+ # value: < |
+ # name: 'IMPORT_BAZ' |
+ # number: 9 |
+ # > |
+ # > |
+ # options: < |
+ # java_package: 'com.google.protobuf.test' |
+ # optimize_for: 1 # SPEED |
+ # > |
+ # public_dependency: 0 |
+ # """) |
+ # self._InternalTestCopyToProto( |
+ # unittest_import_pb2.DESCRIPTOR, |
+ # descriptor_pb2.FileDescriptorProto, |
+ # UNITTEST_IMPORT_FILE_DESCRIPTOR_ASCII) |
def testCopyToProto_ServiceDescriptor(self): |
TEST_SERVICE_ASCII = """ |
@@ -586,28 +713,109 @@ class DescriptorCopyToProtoTest(unittest.TestCase): |
output_type: '.protobuf_unittest.BarResponse' |
> |
""" |
- |
- self._InternalTestCopyToProto( |
- unittest_pb2.TestService.DESCRIPTOR, |
- descriptor_pb2.ServiceDescriptorProto, |
- TEST_SERVICE_ASCII) |
+ # TODO(rocking): enable this test after the proto descriptor change is |
+ # checked in. |
+ #self._InternalTestCopyToProto( |
+ # unittest_pb2.TestService.DESCRIPTOR, |
+ # descriptor_pb2.ServiceDescriptorProto, |
+ # TEST_SERVICE_ASCII) |
class MakeDescriptorTest(unittest.TestCase): |
+ |
+ def testMakeDescriptorWithNestedFields(self): |
+ file_descriptor_proto = descriptor_pb2.FileDescriptorProto() |
+ file_descriptor_proto.name = 'Foo2' |
+ message_type = file_descriptor_proto.message_type.add() |
+ message_type.name = file_descriptor_proto.name |
+ nested_type = message_type.nested_type.add() |
+ nested_type.name = 'Sub' |
+ enum_type = nested_type.enum_type.add() |
+ enum_type.name = 'FOO' |
+ enum_type_val = enum_type.value.add() |
+ enum_type_val.name = 'BAR' |
+ enum_type_val.number = 3 |
+ field = message_type.field.add() |
+ field.number = 1 |
+ field.name = 'uint64_field' |
+ field.label = descriptor.FieldDescriptor.LABEL_REQUIRED |
+ field.type = descriptor.FieldDescriptor.TYPE_UINT64 |
+ field = message_type.field.add() |
+ field.number = 2 |
+ field.name = 'nested_message_field' |
+ field.label = descriptor.FieldDescriptor.LABEL_REQUIRED |
+ field.type = descriptor.FieldDescriptor.TYPE_MESSAGE |
+ field.type_name = 'Sub' |
+ enum_field = nested_type.field.add() |
+ enum_field.number = 2 |
+ enum_field.name = 'bar_field' |
+ enum_field.label = descriptor.FieldDescriptor.LABEL_REQUIRED |
+ enum_field.type = descriptor.FieldDescriptor.TYPE_ENUM |
+ enum_field.type_name = 'Foo2.Sub.FOO' |
+ |
+ result = descriptor.MakeDescriptor(message_type) |
+ self.assertEqual(result.fields[0].cpp_type, |
+ descriptor.FieldDescriptor.CPPTYPE_UINT64) |
+ self.assertEqual(result.fields[1].cpp_type, |
+ descriptor.FieldDescriptor.CPPTYPE_MESSAGE) |
+ self.assertEqual(result.fields[1].message_type.containing_type, |
+ result) |
+ self.assertEqual(result.nested_types[0].fields[0].full_name, |
+ 'Foo2.Sub.bar_field') |
+ self.assertEqual(result.nested_types[0].fields[0].enum_type, |
+ result.nested_types[0].enum_types[0]) |
+ |
def testMakeDescriptorWithUnsignedIntField(self): |
file_descriptor_proto = descriptor_pb2.FileDescriptorProto() |
file_descriptor_proto.name = 'Foo' |
message_type = file_descriptor_proto.message_type.add() |
message_type.name = file_descriptor_proto.name |
+ enum_type = message_type.enum_type.add() |
+ enum_type.name = 'FOO' |
+ enum_type_val = enum_type.value.add() |
+ enum_type_val.name = 'BAR' |
+ enum_type_val.number = 3 |
field = message_type.field.add() |
field.number = 1 |
field.name = 'uint64_field' |
field.label = descriptor.FieldDescriptor.LABEL_REQUIRED |
field.type = descriptor.FieldDescriptor.TYPE_UINT64 |
+ enum_field = message_type.field.add() |
+ enum_field.number = 2 |
+ enum_field.name = 'bar_field' |
+ enum_field.label = descriptor.FieldDescriptor.LABEL_REQUIRED |
+ enum_field.type = descriptor.FieldDescriptor.TYPE_ENUM |
+ enum_field.type_name = 'Foo.FOO' |
+ |
result = descriptor.MakeDescriptor(message_type) |
self.assertEqual(result.fields[0].cpp_type, |
descriptor.FieldDescriptor.CPPTYPE_UINT64) |
+ def testMakeDescriptorWithOptions(self): |
+ descriptor_proto = descriptor_pb2.DescriptorProto() |
+ aggregate_message = unittest_custom_options_pb2.AggregateMessage |
+ aggregate_message.DESCRIPTOR.CopyToProto(descriptor_proto) |
+ reformed_descriptor = descriptor.MakeDescriptor(descriptor_proto) |
+ |
+ options = reformed_descriptor.GetOptions() |
+ self.assertEqual(101, |
+ options.Extensions[unittest_custom_options_pb2.msgopt].i) |
+ |
+ def testCamelcaseName(self): |
+ descriptor_proto = descriptor_pb2.DescriptorProto() |
+ descriptor_proto.name = 'Bar' |
+ names = ['foo_foo', 'FooBar', 'fooBaz', 'fooFoo', 'foobar'] |
+ camelcase_names = ['fooFoo', 'fooBar', 'fooBaz', 'fooFoo', 'foobar'] |
+ for index in range(len(names)): |
+ field = descriptor_proto.field.add() |
+ field.number = index + 1 |
+ field.name = names[index] |
+ result = descriptor.MakeDescriptor(descriptor_proto) |
+ for index in range(len(camelcase_names)): |
+ self.assertEqual(result.fields[index].camelcase_name, |
+ camelcase_names[index]) |
+ |
+ |
if __name__ == '__main__': |
unittest.main() |